Global: Put hoods into table and use smallint for reference

This will reduce size of stats_hood and, more importantly,
make hood assignment independent of hood name changes:

Previouly: Name change = changing string in every place
Now: Name change = change of one table entry

This requires changes to the MySQL database!

Signed-off-by: Adrian Schmutzler <freifunk@adrianschmutzler.de>
This commit is contained in:
Adrian Schmutzler 2018-08-28 15:28:25 +02:00
parent dd6d101ccd
commit 0bf2312fe4
13 changed files with 124 additions and 60 deletions

View File

@ -10,6 +10,33 @@ mysql = FreifunkMySQL()
mysql.execute("""
CREATE TABLE hoods (
id smallint(6) UNSIGNED NOT NULL,
name varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
""")
mysql.execute("""
ALTER TABLE hoods
ADD PRIMARY KEY (id),
ADD UNIQUE KEY name (name)
""")
mysql.execute("""
ALTER TABLE hoods
MODIFY id smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT
""")
mysql.execute("""
ALTER TABLE hoods AUTO_INCREMENT = 30001
""")
mysql.execute("""
INSERT INTO hoods (id, name)
VALUES (%s, %s)
""",(10000,NoCoordinates,))
mysql.execute("""
CREATE TABLE hoodsv1 (
`id` int(11) NOT NULL,
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`net` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
@ -21,7 +48,7 @@ mysql.execute("""
""")
mysql.execute("""
ALTER TABLE hoods
ALTER TABLE hoodsv1
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `name` (`name`),
ADD KEY `lat` (`lat`),
@ -30,11 +57,6 @@ mysql.execute("""
ADD KEY `sin_lat` (`sin_lat`)
""")
mysql.execute("""
INSERT INTO hoods (id, name, net, lat, lng, cos_lat, sin_lat)
VALUES (%s, %s, %s, %s, %s, %s, %s)
""",(0,NoCoordinates,"",None,None,None,None,))
mysql.execute("""
CREATE TABLE hoodsv2 (
`id` int(11) NOT NULL,

View File

@ -92,7 +92,7 @@ mysql.execute("""
`description` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`position_comment` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`community` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`hood` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`hood` smallint(5) UNSIGNED DEFAULT NULL,
`v2` tinyint(1) NOT NULL,
`local` tinyint(1) NOT NULL,
`gateway` tinyint(1) NOT NULL,

View File

@ -47,7 +47,7 @@ mysql.execute("""
mysql.execute("""
CREATE TABLE stats_hood (
`time` int(11) NOT NULL,
`hood` varchar(30) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`hood` smallint(5) UNSIGNED NOT NULL,
`clients` mediumint(9) NOT NULL,
`online` smallint(6) NOT NULL,
`offline` smallint(6) NOT NULL,

View File

@ -62,15 +62,15 @@ def update_hoods_v1(mysql):
kx_data.append((kx["id"],kx["name"],kx["net"],kx.get("lat",None),kx.get("lon",None),cos_lat,sin_lat,))
# Delete entries in DB where hood is missing in KeyXchange
db_keys = mysql.fetchall("SELECT id FROM hoods",(),"id")
db_keys = mysql.fetchall("SELECT id FROM hoodsv1",(),"id")
for n in db_keys:
if n in kx_keys or n==0:
continue
mysql.execute("DELETE FROM hoods WHERE id = %s",(n,))
mysql.execute("DELETE FROM hoodsv1 WHERE id = %s",(n,))
# Create/update entries from KeyXchange to DB
mysql.executemany("""
INSERT INTO hoods (id, name, net, lat, lng, cos_lat, sin_lat)
INSERT INTO hoodsv1 (id, name, net, lat, lng, cos_lat, sin_lat)
VALUES (%s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
name=VALUES(name),

View File

@ -215,7 +215,7 @@ def update_mapnik_csv(mysql):
csv.write("\"LINESTRING (%f %f,%f %f)\"\n" % link)
dbhoods = mysql.fetchall("""
SELECT name, lat, lng FROM hoods
SELECT name, lat, lng FROM hoodsv1
WHERE lat IS NOT NULL AND lng IS NOT NULL
""")
with open(os.path.join(CONFIG["csv_dir"], "hood-points.csv"), "w", encoding="UTF-8") as csv:

View File

@ -136,7 +136,7 @@ def defrag_table(mysql,table,sleep):
print("--- Defragmented table %s: %.3f seconds ---" % (table,end_time - start_time))
def defrag_all(mysql,doall=False):
alltables = ('gw','gw_admin','gw_netif','hoods','hoodsv2','netifs','router','router_events','router_gw','router_ipv6','router_neighbor','router_netif','users')
alltables = ('gw','gw_admin','gw_netif','hoods','hoodsv1','hoodsv2','netifs','router','router_events','router_gw','router_ipv6','router_neighbor','router_netif','users')
stattables = ('router_stats','router_stats_gw','router_stats_neighbor','router_stats_netif','stats_global','stats_gw','stats_hood')
for t in alltables:

View File

@ -43,7 +43,7 @@ def ban_router(mysql,dbid):
mysql.execute("INSERT INTO banned (mac, added) VALUES (%s, %s)",(mac,added,))
mysql.commit()
def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstime):
def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, hoodsdict, statstime):
#global router_rate_limit_list
#if mac in router_rate_limit_list:
@ -78,7 +78,13 @@ def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstim
if findrouter:
router_id = findrouter["router"]
olddata = mysql.findone("SELECT sys_uptime, sys_time, firmware, hostname, hood, status, lat, lng, contact, description, position_comment, w2_active, w2_busy, w5_active, w5_busy FROM router WHERE id = %s LIMIT 1",(router_id,))
olddata = mysql.findone("""
SELECT sys_uptime, sys_time, firmware, hostname, hoods.id AS hoodid, hoods.name AS hood, status, lat, lng, contact, description, position_comment, w2_active, w2_busy, w5_active, w5_busy
FROM router
LEFT JOIN hoods ON router.hood = hoods.id
WHERE router.id = %s
LIMIT 1
""",(router_id,))
if olddata:
uptime = olddata["sys_uptime"]
@ -110,20 +116,32 @@ def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstim
)
) AS distance
FROM
hoods
hoodsv1
WHERE lat IS NOT NULL AND lng IS NOT NULL
ORDER BY
distance ASC
LIMIT 1
""",(lat,lng,lat,),"name")
if not router_update["hood"]:
router_update["hood"] = "Default"
router_update["hood"] = "DefaultV1"
if router_update["neighbours"] and not router_update["has_wan_uplink"]:
router_update["hood"] = "NoCoordinates"
if not router_update['lat'] and not router_update['lng'] and olddata and olddata['lat'] and olddata['lng']:
# Enable reset state; do before variable fallback
reset = True
if not router_update["hood"] in hoodsdict.keys():
checkagain = mysql.findone("SELECT id FROM hoods WHERE name = %s",(router_update["hood"],),"id")
# Prevent adding the same hood for all routers (won't break, but each will raise the AUTO_INCREMENT)
if not checkagain:
mysql.execute("""
INSERT INTO hoods (name)
VALUES (%s)
ON DUPLICATE KEY UPDATE name=name
""",(router_update["hood"],))
hoodsdict = mysql.fetchdict("SELECT id, name FROM hoods",(),"name","id")
router_update["hoodid"] = hoodsdict[router_update["hood"]]
if not router_update['hostname']:
router_update['hostname'] = 'Give Me A Name'
@ -173,7 +191,7 @@ def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstim
ru["sys_loadavg"],ru["processes"]["runnable"],ru["processes"]["total"],ru["clients"],ru["clients_eth"],ru["clients_w2"],ru["clients_w5"],
ru["w2_active"],ru["w2_busy"],ru["w5_active"],ru["w5_busy"],ru["w2_airtime"],ru["w5_airtime"],ru["has_wan_uplink"],ru["tc_enabled"],ru["tc_in"],ru["tc_out"],
ru["cpu"],ru["chipset"],ru["hardware"],ru["os"],
ru["batman_adv"],ru["rt_protocol"],ru["kernel"],ru["nodewatcher"],ru["firmware"],ru["firmware_rev"],ru["description"],ru["position_comment"],ru["community"],ru["hood"],ru["v2"],ru["local"],ru["gateway"],
ru["batman_adv"],ru["rt_protocol"],ru["kernel"],ru["nodewatcher"],ru["firmware"],ru["firmware_rev"],ru["description"],ru["position_comment"],ru["community"],ru["hoodid"],ru["v2"],ru["local"],ru["gateway"],
ru["status_text"],ru["contact"],ru["lng"],ru["lat"],ru["visible_neighbours"],reset,router_id,))
# Previously, I just deleted all entries and recreated them again with INSERT.
@ -246,7 +264,7 @@ def import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstim
ru["sys_loadavg"],ru["processes"]["runnable"],ru["processes"]["total"],ru["clients"],ru["clients_eth"],ru["clients_w2"],ru["clients_w5"],
None,None,None,None,None,None,ru["has_wan_uplink"],ru["tc_enabled"],ru["tc_in"],ru["tc_out"],
ru["cpu"],ru["chipset"],ru["hardware"],ru["os"],
ru["batman_adv"],ru["rt_protocol"],ru["kernel"],ru["nodewatcher"],ru["firmware"],ru["firmware_rev"],ru["description"],ru["position_comment"],ru["community"],ru["hood"],ru["v2"],ru["local"],ru["gateway"],
ru["batman_adv"],ru["rt_protocol"],ru["kernel"],ru["nodewatcher"],ru["firmware"],ru["firmware_rev"],ru["description"],ru["position_comment"],ru["community"],ru["hoodid"],ru["v2"],ru["local"],ru["gateway"],
ru["status_text"],ru["contact"],ru["lng"],ru["lat"],ru["visible_neighbours"],))
router_id = mysql.cursor().lastrowid

View File

@ -199,17 +199,19 @@ def router_firmwares(mysql,selecthood=None,selectgw=None):
def hoods(mysql,selectgw=None):
data = mysql.fetchall("""
SELECT hood, status, COUNT(id) AS count
SELECT hoods.id AS hoodid, hoods.name AS hood, status, COUNT(router.id) AS count
FROM router
GROUP BY hood, status
LEFT JOIN hoods ON router.hood = hoods.id
GROUP BY hoods.id, hoods.name, status
""")
result = {}
for rs in data:
if not rs["hood"]:
rs["hood"] = "Default"
if not rs["hood"] in result:
result[rs["hood"]] = {}
result[rs["hood"]][rs["status"]] = rs["count"]
rs["hoodid"] = "1"
rs["hood"] = "NoHood"
if not rs["hoodid"] in result:
result[rs["hoodid"]] = {'name':rs["hood"]}
result[rs["hoodid"]][rs["status"]] = rs["count"]
return result
def hoods_sum(mysql,selectgw=None):

View File

@ -92,7 +92,6 @@ def get_nearest_router():
) AS distance
FROM
router AS r
LEFT JOIN hoods AS h ON r.hood = h.name
WHERE r.lat IS NOT NULL AND r.lng IS NOT NULL """ + where + """
ORDER BY
distance ASC
@ -155,6 +154,7 @@ def alfred():
""",(),"name")
statstime = utcnow()
netifdict = mysql.fetchdict("SELECT id, name FROM netifs",(),"name","id")
hoodsdict = mysql.fetchdict("SELECT id, name FROM hoods",(),"name","id")
if request.method == 'POST':
try:
alfred_data = request.get_json()
@ -167,7 +167,7 @@ def alfred():
# load router status xml data
i = 1
for mac, xml in alfred_data.get("64", {}).items():
import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, statstime)
import_nodewatcher_xml(mysql, mac, xml, banned, hoodsv2, netifdict, hoodsdict, statstime)
if (i%500 == 0):
mysql.commit()
i += 1
@ -260,8 +260,9 @@ def wifianal(selecthood):
SELECT hostname, mac, netif
FROM router
INNER JOIN router_netif ON router.id = router_netif.router
WHERE hood = %s
GROUP BY id, netif
INNER JOIN hoods ON router.hood = hoods.id
WHERE hoods.name = %s
GROUP BY router.id, netif
""",(selecthood,))
mysql.close()
@ -351,8 +352,9 @@ def routers():
# Suppresses routers without br-mesh
mysql = FreifunkMySQL()
router_data = mysql.fetchall("""
SELECT router.id, hostname, status, hood, contact, nickname, hardware, firmware, clients, lat, lng, last_contact, mac, sys_loadavg
SELECT router.id, hostname, status, hoods.id AS hoodid, hoods.name AS hood, contact, nickname, hardware, firmware, clients, lat, lng, last_contact, mac, sys_loadavg
FROM router
INNER JOIN hoods ON router.hood = hoods.id
INNER JOIN router_netif ON router.id = router_netif.router
LEFT JOIN users ON router.contact = users.email
WHERE netif = 'br-mesh'
@ -394,6 +396,7 @@ def routers():
'id': str(router['id']),
'name': router['hostname'],
'mac': int2mac(router['mac']),
'hoodid': router['hoodid'],
'hood': router['hood'],
'status': router['status'],
'user': router['nickname'],
@ -487,7 +490,7 @@ def get_routers_by_keyxchange_id(keyxchange_id):
mysql = FreifunkMySQL()
hood = mysql.findone("""
SELECT name
FROM hoods
FROM hoodsv1
WHERE id = %s
LIMIT 1
""",(int(keyxchange_id),))
@ -501,7 +504,8 @@ def get_routers_by_keyxchange_id(keyxchange_id):
SELECT router.id, hostname, hardware, mac, fe80_addr, firmware, lat, lng, contact, position_comment, description
FROM router
INNER JOIN router_netif ON router.id = router_netif.router
WHERE hood = %s AND netif = 'br-mesh'
INNER JOIN hoods ON router.hood = hoods.id
WHERE hoods.name = %s AND netif = 'br-mesh'
ORDER BY hostname ASC
""",(hood["name"],))
mysql.close()

View File

@ -52,8 +52,9 @@ def router_list():
mysql = FreifunkMySQL()
routers = mysql.fetchall("""
SELECT router.id, hostname, status, hood, contact, nickname, hardware, router.created, sys_uptime, last_contact, clients, reset, blocked, v2, local
SELECT router.id, hostname, status, hoods.id AS hoodid, hoods.name AS hood, contact, nickname, hardware, router.created, sys_uptime, last_contact, clients, reset, blocked, v2, local
FROM router
INNER JOIN hoods ON router.hood = hoods.id
LEFT JOIN users ON router.contact = users.email
LEFT JOIN (
SELECT router, blocked.mac AS blocked FROM router_netif
@ -95,7 +96,11 @@ def router_mac(mac):
def router_info(dbid):
try:
mysql = FreifunkMySQL()
router = mysql.findone("""SELECT * FROM router WHERE id = %s LIMIT 1""",(dbid,))
router = mysql.findone("""
SELECT router.*, hoods.id AS hoodid, hoods.name AS hoodname FROM router
INNER JOIN hoods ON router.hood = hoods.id
WHERE router.id = %s LIMIT 1
""",(dbid,))
mac = None
if router:
@ -451,8 +456,9 @@ def user_info(nickname):
else:
flash("<b>You are not authorized to perform this action!</b>", "danger")
routers = mysql.fetchall("""
SELECT id, hostname, status, hood, firmware, hardware, created, sys_uptime, clients, reset, blocked, v2, local
SELECT router.id, hostname, status, hoods.id AS hoodid, hoods.name AS hood, firmware, hardware, created, sys_uptime, clients, reset, blocked, v2, local
FROM router
INNER JOIN hoods ON router.hood = hoods.id
LEFT JOIN (
SELECT router, blocked.mac AS blocked FROM router_netif
INNER JOIN blocked ON router_netif.mac = blocked.mac
@ -480,6 +486,7 @@ def global_statistics():
@app.route('/hoodstatistics/<selecthood>')
def global_hoodstatistics(selecthood):
selecthood = int(selecthood)
mysql = FreifunkMySQL()
stats = mysql.fetchall("SELECT * FROM stats_hood WHERE hood = %s",(selecthood,))
return helper_statistics(mysql,stats,selecthood,None)
@ -496,12 +503,17 @@ def helper_statistics(mysql,stats,selecthood,selectgw):
hoods = stattools.hoods(mysql,selectgw)
gws = stattools.gws(mysql,selecthood)
if selecthood:
selecthoodname = mysql.findone("SELECT name FROM hoods WHERE id = %s",(selecthood,),'name')
else:
selecthoodname = None
if selectgw:
selectgwint = mac2int(selectgw)
else:
selectgwint = None
if selecthood and not selecthood in hoods:
if selecthood and not selecthood in hoods.keys():
mysql.close()
return "Hood not found"
if selectgw and not selectgwint in gws:
@ -516,8 +528,9 @@ def helper_statistics(mysql,stats,selecthood,selectgw):
if selectgw:
newest_routers = mysql.fetchall("""
SELECT id, hostname, hood, created
SELECT router.id, hostname, hoods.id AS hoodid, hoods.name AS hood, created
FROM router
INNER JOIN hoods ON router.hood = hoods.id
INNER JOIN router_gw ON router.id = router_gw.router
WHERE hardware <> 'Legacy' AND mac = %s
ORDER BY created DESC
@ -525,14 +538,15 @@ def helper_statistics(mysql,stats,selecthood,selectgw):
""",(mac2int(selectgw),numnew,))
else:
if selecthood:
where = " AND hood = %s"
where = " AND hoods.id = %s"
tup = (selecthood,numnew,)
else:
where = ""
tup = (numnew,)
newest_routers = mysql.fetchall("""
SELECT id, hostname, hood, created
SELECT router.id, hostname, hoods.id AS hoodid, hoods.name AS hood, created
FROM router
INNER JOIN hoods ON router.hood = hoods.id
WHERE hardware <> 'Legacy' {}
ORDER BY created DESC
LIMIT %s
@ -552,6 +566,7 @@ def helper_statistics(mysql,stats,selecthood,selectgw):
return render_template("statistics.html",
selecthood = selecthood,
selecthoodname = selecthoodname,
selectgw = selectgw,
selectgwint = selectgwint,
stats = stats,

View File

@ -100,7 +100,10 @@ def parse_router_list_search_query(args):
j += " INNER JOIN ( SELECT router, mac FROM router_neighbor GROUP BY router, mac) AS j ON router.id = j.router "
k = "HEX(mac) {} REGEXP %s".format(no)
t.append(value.replace(':',''))
elif (key == 'hardware') or (key == 'hood') or (key == 'nickname'):
elif (key == 'hood'):
k = "hoods.name {} REGEXP %s".format(no)
t.append(value.replace("_","."))
elif (key == 'hardware') or (key == 'nickname'):
k = key + " {} REGEXP %s".format(no)
t.append(value.replace("_","."))
elif (key == 'hostname') or (key == 'firmware'):

View File

@ -139,8 +139,8 @@
{%- if router.position_comment %}
<tr><th>Position</th><td>{{ router.position_comment }}</td></tr>
{%- endif %}
{%- if router.hood %}
<tr><th>Hood</th><td{%- if router.local %} class="hoodlocal"{%- elif router.v2 %} class="hoodv2"{%- endif %}><a href="{{ url_for('router_list', q='hood:^%s$' % router.hood) }}">{{ router.hood }}</a>
{%- if router.hoodname %}
<tr><th>Hood</th><td{%- if router.local %} class="hoodlocal"{%- elif router.v2 %} class="hoodv2"{%- endif %}><a href="{{ url_for('router_list', q='hood:^%s$' % router.hoodname) }}">{{ router.hoodname }}</a>
{%- if router.community %}
({{ router.community }})
{%- endif -%}

View File

@ -1,5 +1,5 @@
{% extends "bootstrap.html" %}
{% block title %}{{super()}} :: Statistics{%- if selecthood %} for {{ selecthood }}{%- endif -%}{%- if selectgw %} for GW {{ selectgw }}{%- endif -%}{% endblock %}
{% block title %}{{super()}} :: Statistics{%- if selecthood %} for {{ selecthoodname }}{%- endif -%}{%- if selectgw %} for GW {{ selectgw }}{%- endif -%}{% endblock %}
{% block head %}{{super()}}
<script src="{{ url_for('static', filename='js/graph/date.js') }}"></script>
<script src="{{ url_for('static', filename='js/graph/jquery.flot.js') }}"></script>
@ -68,16 +68,16 @@
</tr>
</thead>
<tbody>
{%- for hood, value in hoods|dictsort %}
{%- for hoodid, value in hoods|dictsort %}
<tr>
<td class="firstrow{%- if hoods_sum[hood]["local"] %} hoodlocal{%- elif hoods_sum[hood]["v2"] %} hoodv2{%- endif %}"><a href="{{ url_for('router_list', q='hood:^%s$' % hood.replace(' ','_')) }}">{{ hood }}</a></td>
<td class="stats">{{ hoods_gws[hood] or "-" }}</td>
<td class="firstrow{%- if hoods_sum[hoodid]["local"] %} hoodlocal{%- elif hoods_sum[hoodid]["v2"] %} hoodv2{%- endif %}"><a href="{{ url_for('router_list', q='hood:^%s$' % value['name'].replace(' ','_')) }}">{{ value['name'] }}</a></td>
<td class="stats">{{ hoods_gws[hoodid] or "-" }}</td>
<td class="success">{{ value["online"] or 0 }}</td>
<td class="danger" data-order="{{ value["offline"] or 0 }}">{{ value["offline"] or 0 }}{%- if value["orphaned"] %} ({{ value["orphaned"] or 0 }}){%- endif %}</td>
<td class="warning">{{ value["unknown"] or 0 }}</td>
<td class="active">{{ hoods_sum[hood]["routers"] }}</td>
<td class="info">{{ hoods_sum[hood]["clients"] }}</td>
<td class="stats"><a href="{{ url_for('global_hoodstatistics', selecthood='%s' % hood) }}">Stats</a></td>
<td class="active">{{ hoods_sum[hoodid]["routers"] }}</td>
<td class="info">{{ hoods_sum[hoodid]["clients"] }}</td>
<td class="stats"><a href="{{ url_for('global_hoodstatistics', selecthood='%s' % hoodid) }}">Stats</a></td>
</tr>
{%- endfor %}
</tbody>
@ -90,7 +90,7 @@
<td class="warning">{{ router_status.unknown or 0 }}</td>
<td class="active">{{ router_status.sum or 0 }}</td>
<td class="info">{{ clients }}</td>
<td class="stats"><a href="{{ url_for('global_statistics') }}">Global</a></td>
<td class="stats"><a href="{{ url_for('global_statistics') }}">Global</a></td>
</tr>
</tfoot>
</table>
@ -99,27 +99,27 @@
</div>
<div class="col-xs-12 col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Routers{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }} (selected only){%- endif -%}</div>
<div class="panel-heading">Routers{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }} (selected only){%- endif -%}</div>
<div class="panel-body">
<div id="globrouterstat" class="graph"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Clients{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }} (selected only){%- endif -%}</div>
<div class="panel-heading">Clients{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }} (selected only){%- endif -%}</div>
<div class="panel-body">
<div id="globclientstat" class="graph"></div>
</div>
</div>
{%- if not selectgw %}
<div class="panel panel-default">
<div class="panel-heading">Traffic{%- if selecthood %} @ {{ selecthood }}{%- endif -%}</div>
<div class="panel-heading">Traffic{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}</div>
<div class="panel-body">
<div id="netstat" class="graph"></div>
</div>
</div>
{%- endif -%}
<div class="panel panel-default">
<div class="panel-heading">Newest Routers{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-heading">Newest Routers{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-body" style="padding-bottom:34px">
<div class="table-responsive">
<table class="table table-condensed">
@ -144,7 +144,7 @@
<div class="row">
<div class="col-xs-12 col-md-6">
<div class="panel panel-default">
<div class="panel-heading">Gateways (selected / others){%- if selecthood %} @ {{ selecthood }}{%- endif -%}</div>
<div class="panel-heading">Gateways (selected / others){%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}</div>
<div class="panel-body">
<table id="gwlist" class="table table-condensed table-hoods">
<thead>
@ -211,19 +211,19 @@
</div>
{%- endif %}
<div class="panel panel-default">
<div class="panel-heading">Router Firmwares{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-heading">Router Firmwares{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-body">
<div id="globrouterfwstat" class="graph-pie"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Router Models{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-heading">Router Models{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-body">
<div id="globroutermodelsstat" class="graph-pie"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">Router Models per Client{%- if selecthood %} @ {{ selecthood }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-heading">Router Models per Client{%- if selecthood %} @ {{ selecthoodname }}{%- endif -%}{%- if selectgw %} @ {{ selectgw }}{%- endif -%}</div>
<div class="panel-body">
<div id="globroutermodelsperclient" class="graph-pie"></div>
</div>
@ -236,7 +236,7 @@
var router_models = {{ router_models|tojson }};
var routers_page_url = "{{ url_for('router_list') }}";
{%- if selecthood %}
var hood = "{{selecthood}}";
var hood = "{{selecthoodname}}";
var hoodstr = "hood:^" + hood.replace(/ /g, '_') + "$";
{%- else %}
var hoodstr = "";