Gentoo Archives: gentoo-commits

From: Max Magorsch <arzano@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/gentoo-mirrorstats:master commit in: html/
Date: Sun, 03 May 2020 22:47:41
Message-Id: 1588545907.1676f2fc64880251befdb18ad22f59dae0ae1f4e.arzano@gentoo
1 commit: 1676f2fc64880251befdb18ad22f59dae0ae1f4e
2 Author: Max Magorsch <arzano <AT> gentoo <DOT> org>
3 AuthorDate: Sun May 3 22:45:07 2020 +0000
4 Commit: Max Magorsch <arzano <AT> gentoo <DOT> org>
5 CommitDate: Sun May 3 22:45:07 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/gentoo-mirrorstats.git/commit/?id=1676f2fc
7
8 Generate html pages based on the mirmon data
9
10 A python script is used to generate html pages based
11 on the data produced by mirmon. The html pages visualize
12 the mirror stats using the gentoo tyrian theme.
13
14 Signed-off-by: Max Magorsch <arzano <AT> gentoo.org>
15
16 html/generate.py | 178 ++++++++++++++++++++++++++++
17 html/help.jinja2 | 163 ++++++++++++++++++++++++++
18 html/stats.jinja2 | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
19 3 files changed, 680 insertions(+)
20
21 diff --git a/html/generate.py b/html/generate.py
22 new file mode 100755
23 index 0000000..d6f21c0
24 --- /dev/null
25 +++ b/html/generate.py
26 @@ -0,0 +1,178 @@
27 +#!/usr/bin/python
28 +
29 +#
30 +# Generate html pages based on the Mirmon data
31 +#
32 +# This script will parse the json files that contain the mirmon
33 +# data and have been generated before. The json data is used to
34 +# generate html pages that visualize the mirmon data in a human
35 +# readable way.
36 +#
37 +#
38 +# Leaflet is used to visualize the mirrors on a world map. Further-
39 +# more Datatables are used to display the mirrors.
40 +#
41 +
42 +import datetime
43 +import socket
44 +import urllib.request, json
45 +import xml.etree.ElementTree as ET
46 +import jinja2
47 +
48 +html_folder = "/var/www/mirrorstats.gentoo.org/htdocs/"
49 +cache_path = "/var/www/mirrorstats.gentoo.org/var/html_data_cache.json"
50 +
51 +
52 +mirrorstats = [ 'https://mirrorstats.gentoo.org/rsync/state.json',
53 + 'https://mirrorstats.gentoo.org/distfiles/state.json',
54 + 'https://mirrorstats.gentoo.org/snapshots/state.json',
55 + 'https://mirrorstats.gentoo.org/releases/state.json',
56 + 'https://mirrorstats.gentoo.org/experimental/state.json'
57 + ]
58 +
59 +cache_data = {}
60 +
61 +
62 +#
63 +# Retrieve and parse the JSON at the given URL
64 +#
65 +def getJson(url):
66 + req = urllib.request.Request(url)
67 + r = urllib.request.urlopen(req).read()
68 + return json.loads(r.decode('utf-8'))
69 +
70 +
71 +#
72 +# Retrieve and parse the XML at the given URL
73 +#
74 +def getXML(url):
75 + req = urllib.request.Request(url)
76 + r = urllib.request.urlopen(req).read()
77 + return ET.loads(r.decode('utf-8')).getroot()
78 +
79 +
80 +#
81 +# Get the ip of the given host
82 +#
83 +def getIp(hostname):
84 + try:
85 + ip = socket.gethostbyname(hostname)
86 + except:
87 + ip = ""
88 + return ip
89 +
90 +
91 +#
92 +# Render the stats template for a given page, i.e. all, rsync, distfiles...
93 +#
94 +def renderStatsTemplate(templateEnv, page):
95 + if page == "all":
96 + mirrorstatsList = mirrorstats
97 + else:
98 + mirrorstatsList = ['https://mirrorstats.gentoo.org/' + page + '/state.json']
99 +
100 + lastUpdate, hostList = getHostList(mirrorstatsList)
101 + template = templateEnv.get_template("stats.jinja2")
102 + template.stream(lastUpdate=lastUpdate, type=page, mirrors=hostList, locations=json.dumps(hostList)).dump(html_folder + page + ".html")
103 + return lastUpdate
104 +
105 +
106 +# read the cache
107 +with open(cache_path) as json_file:
108 + cache_data = json.load(json_file)
109 +
110 +#
111 +# The all mirrors that are present in the given list
112 +#
113 +def getHostList(mirrorstatsList):
114 + hosts = {}
115 + lastUpdate = ""
116 +
117 + # process all mirrors
118 + for mirror_url in mirrorstatsList:
119 +
120 + mirrorData = getJson(mirror_url)
121 + lastUpdate = datetime.datetime.fromtimestamp(int(mirrorData['LastUpdate'])).strftime('%Y-%m-%d %H:%M:%S')
122 +
123 + for mirror in mirrorData['Mirrors']:
124 + if len(mirrorData['Mirrors'][mirror]) >= 0:
125 + for mirrorHost in mirrorData['Mirrors'][mirror]:
126 + hostname = mirrorHost['Host']
127 + if hostname not in hosts:
128 + hosts[hostname] = {}
129 +
130 + hosts[hostname]['Hostname'] = hostname
131 +
132 + if hostname in cache_data['hosts']:
133 + ip = cache_data['hosts'][hostname]
134 + else:
135 + ip = getIp(hostname)
136 + # populate cache with new value
137 + cache_data['hosts'][hostname] = ip
138 +
139 + if ip != "":
140 + hosts[hostname]['Ip'] = ip
141 +
142 + if 'Stats' not in hosts[hostname]:
143 + hosts[hostname]['Stats'] = []
144 +
145 + mirrorHost['Type'] = mirror_url.replace("https://mirrorstats.gentoo.org/", "").replace("/state.json", "")
146 + hosts[hostname]['Stats'].append(mirrorHost)
147 +
148 + # compute available protocols
149 + for host in hosts:
150 + protocols = []
151 + for stat in hosts[host]['Stats']:
152 + protocols.append(stat['Protocol'])
153 +
154 + hosts[host]['Protocols'] = list(set(protocols))
155 +
156 + # compute mirror locations
157 + for host in hosts:
158 + if 'Ip' not in hosts[host]:
159 + continue
160 +
161 + ip = hosts[host]['Ip']
162 + if ip in cache_data['ips']:
163 + hosts[host]['Location'] = cache_data['ips'][ip]
164 + else:
165 + mirrorGeoData = getJson("https://ipinfo.io/" + ip + "/json")
166 + hosts[host]['Location'] = mirrorGeoData['loc']
167 + # populate cache with new value
168 + cache_data['ips'][ip] = mirrorGeoData['loc']
169 +
170 + return lastUpdate, hosts
171 +
172 +
173 +#
174 +# render jinja2
175 +#
176 +templateLoader = jinja2.FileSystemLoader(searchpath="./")
177 +templateEnv = jinja2.Environment(loader=templateLoader)
178 +
179 +## stats
180 +lastUpdate = renderStatsTemplate(templateEnv, "all")
181 +renderStatsTemplate(templateEnv, "rsync")
182 +renderStatsTemplate(templateEnv, "distfiles")
183 +renderStatsTemplate(templateEnv, "snapshots")
184 +renderStatsTemplate(templateEnv, "releases")
185 +renderStatsTemplate(templateEnv, "experimental")
186 +
187 +## about
188 +template = templateEnv.get_template("help.jinja2")
189 +template.stream(lastUpdate=lastUpdate).dump(html_folder + "help.html")
190 +
191 +
192 +#
193 +# write the cache
194 +#
195 +with open(cache_path, 'w') as fp:
196 + json.dump(cache_data, fp)
197 +
198 +
199 +#
200 +# finish
201 +#
202 +print("Finished.")
203 +
204 +
205
206 diff --git a/html/help.jinja2 b/html/help.jinja2
207 new file mode 100644
208 index 0000000..6e08363
209 --- /dev/null
210 +++ b/html/help.jinja2
211 @@ -0,0 +1,163 @@
212 +<!DOCTYPE html>
213 +<html>
214 + <head>
215 + <title>Gentoo Mirrorstats</title>
216 + <meta charset="utf-8">
217 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
218 + <link href="https://assets.gentoo.org/tyrian/v2/tyrian.min.css" rel="stylesheet" media="screen">
219 + <link rel="icon" href="https://www.gentoo.org/favicon.ico" type="image/x-icon">
220 + </head>
221 +
222 + <body>
223 +
224 + <header>
225 + <div class="site-title">
226 + <div class="container">
227 + <div class="row justify-content-between">
228 + <div class="logo">
229 + <a href="/" title="Back to the homepage" class="site-logo">
230 + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo" srcset="https://assets.gentoo.org/tyrian/v2/site-logo.svg">
231 + </a>
232 + <span class="site-label">Mirrorstats</span>
233 + </div>
234 + <div class="site-title-buttons">
235 + <div class="btn-group btn-group-sm">
236 + <a href="https://get.gentoo.org/" role="button" class="btn get-gentoo"><span class="fa fa-fw fa-download"></span> <strong>Get Gentoo!</strong></a>
237 + <div class="btn-group btn-group-sm">
238 + <a class="btn gentoo-org-sites dropdown-toggle" data-toggle="dropdown" data-target="#" href="#">
239 + <span class="fa fa-fw fa-map-o"></span> <span class="d-none d-sm-inline">gentoo.org sites</span> <span class="caret"></span>
240 + </a>
241 + <div class="dropdown-menu dropdown-menu-right">
242 + <a class="dropdown-item" href="https://www.gentoo.org/" title="Main Gentoo website"><span class="fa fa-home fa-fw"></span> gentoo.org</a>
243 + <a class="dropdown-item" href="https://wiki.gentoo.org/" title="Find and contribute documentation"><span class="fa fa-file-text-o fa-fw"></span> Wiki</a>
244 + <a class="dropdown-item" href="https://bugs.gentoo.org/" title="Report issues and find common issues"><span class="fa fa-bug fa-fw"></span> Bugs</a>
245 + <a class="dropdown-item" href="https://forums.gentoo.org/" title="Discuss with the community"><span class="fa fa-comments-o fa-fw"></span> Forums</a>
246 + <a class="dropdown-item" href="https://packages.gentoo.org/" title="Find software for your Gentoo"><span class="fa fa-hdd-o fa-fw"></span> Packages</a>
247 + <div class="dropdown-divider"></div>
248 + <a class="dropdown-item" href="https://planet.gentoo.org/" title="Find out what's going on in the developer community"><span class="fa fa-rss fa-fw"></span> Planet</a>
249 + <a class="dropdown-item" href="https://archives.gentoo.org/" title="Read up on past discussions"><span class="fa fa-archive fa-fw"></span> Archives</a>
250 + <a class="dropdown-item" href="https://sources.gentoo.org/" title="Browse our source code"><span class="fa fa-code fa-fw"></span> Sources</a>
251 + <div class="dropdown-divider"></div>
252 + <a class="dropdown-item" href="https://infra-status.gentoo.org/" title="Get updates on the services provided by Gentoo"><span class="fa fa-server fa-fw"></span> Infra Status</a>
253 + </div>
254 + </div>
255 + </div>
256 + </div>
257 + </div>
258 + </div>
259 + </div>
260 + <nav class="tyrian-navbar navbar navbar-dark navbar-expand-lg bg-primary" role="navigation">
261 + <div class="container">
262 + <div class="navbar-header">
263 + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-main-collapse" aria-controls="navbar-main-collapse" aria-expanded="false" aria-label="Toggle navigation">
264 + <span class="navbar-toggler-icon"></span>
265 + </button>
266 + </div>
267 + <div class="collapse navbar-collapse navbar-main-collapse" id="navbar-main-collapse">
268 + <ul class="navbar-nav mr-auto">
269 + <li class="nav-item"><a class="nav-link" href="all.html">Home</a></li>
270 + <li class="nav-item"><a class="nav-link" href="rsync.html">Rsync</a></li>
271 + <li class="nav-item"><a class="nav-link" href="distfiles.html">Distfiles</a></li>
272 + <li class="nav-item"><a class="nav-link" href="snapshots.html">Snapshots</a></li>
273 + <li class="nav-item"><a class="nav-link" href="releases.html">Releases</a></li>
274 + <li class="nav-item"><a class="nav-link" href="experimental.html">Experimental</a></li>
275 + <li class="nav-item active"><a class="nav-link" href="help.html">Help</a></li>
276 + </ul>
277 + </div>
278 + </div>
279 + </nav>
280 + </header>
281 +
282 +
283 + <div class="container">
284 + <div class="row">
285 + <div class="col-md-12">
286 + <h1 class="first-header">About Gentoo Mirrors</h1>
287 + <div class="alert alert-info">
288 + If you experience problems with this site (<tt>mirrorstats.gentoo.org</tt>), please file clearly marked bugs in
289 + <a href="https://bugs.gentoo.org/enter_bug.cgi?assigned_to=infra-bugs%40gentoo.org&bug_file_loc=http%3A%2F%2F&bug_severity=normal&bug_status=CONFIRMED&cf_runtime_testing_required=---&comment=This%20page%20is%20NOT%20for%20problems%20with%20a%20specific%20mirror.%0D%0A%0D%0APlease%20include%20a%20summary%20of%20your%20problem%20with%20mirrorstats.gentoo.org%20here.%0D%0A%0D%0A&component=Other%20web%20server%20issues&contenttypemethod=autodetect&contenttypeselection=text%2Fplain&defined_groups=1&flag_type-4=X&form_name=enter_bug&maketemplate=Remember%20values%20as%20bookmarkable%20template&op_sys=Linux&priority=Normal&product=Gentoo%20Infrastructure&rep_platform=All&short_desc=mirrorstats.gentoo.org%3A%20PROBLEM%20SUMMARY&version=unspecified">Gentoo Bugzilla (product <i>Infrastructure</i>)</a>.
290 + Please remember to include <tt>mirrorstats</tt> in the summary line.
291 + </div>
292 + <h2 id="moreInformation">Gentoo rsync mirrors</h2>
293 + <p>Gentoo rsync mirrors tracked include both official mirrors run by the Gentoo Infrastructure team, as well as community-run mirrors.</p>
294 + <ul>
295 + <li><a href="https://www.gentoo.org/support/rsync-mirrors/">Listing of Gentoo rsync mirrors</a></li>
296 + <li><a href="https://wiki.gentoo.org/wiki/Project:Infrastructure/Mirrors/Rsync">How to contribute a new rsync mirror</a></li>
297 + <li><a href="/rsync/">Status of Gentoo rsync mirrors</a></li>
298 + </ul>
299 + <h2>Gentoo source mirrors</h2>
300 + <ul>
301 + <li><a href="https://www.gentoo.org/downloads/mirrors/">Listing of Gentoo source mirrors</a></li>
302 + <li><a href="https://wiki.gentoo.org/wiki/Project:Infrastructure/Mirrors/Source">How to contribute a new source mirror</a></li>
303 + <li><a href="/distfiles/">Status of Gentoo source mirrors: <tt>/distfiles/</tt></a>
304 + <li><a href="/experimental/">Status of Gentoo source mirrors: <tt>/experimental/</tt></a>
305 + <li><a href="/releases/">Status of Gentoo source mirrors: <tt>/releases/</tt></a>
306 + <li><a href="/snapshots/">Status of Gentoo source mirrors: <tt>/snapshots/</tt></a>
307 + </ul>
308 + <div class="alert alert-warning">
309 + If you experience problems with a specific mirror, please file clearly marked bugs in <a href="https://bugs.gentoo.org/enter_bug.cgi?product=Mirrors">Gentoo Bugzilla (product <i>Mirrors</i>)</a>.</br>
310 + Please include lots of details about the problem, as the Gentoo
311 + mirror team will have to contact the administrator of individual
312 + mirrors to work on problems.
313 + <ul>
314 + <li><b>Hostname</b> of the mirror (in the summary &amp; description)</li>
315 + <li><b>IP</b> of the mirror: many mirrors have multiple nodes behind a single DNS entry</li>
316 + <li><b>Timestamp</b> of the problem</li>
317 + <li><b>Logs</b> of the problem</li>
318 + </ul>
319 + </div>
320 + </div>
321 + </div>
322 + </div>
323 +
324 +
325 + <footer>
326 + <div class="container">
327 + <div class="row">
328 + <div class="col-12 offset-md-2 col-md-7">
329 + <h3 class="footerhead">Gentoo Mirrorstats</h3>
330 + <div class="row">
331 + <div class="col-xs-12 col-md-4">
332 + <span class="kk-group-header">Mirror Data as current of</span><br>{{ lastUpdate }}
333 + </div>
334 + <div class="col-xs-12 col-md-4">
335 + </div>
336 + <div class="col-xs-12 col-md-4">
337 + </div>
338 + </div>
339 + </div>
340 + <div class="col-12 col-md-3">
341 + <h3 class="footerhead">Questions or comments?</h3>
342 + Please feel free to <a href="https://www.gentoo.org/inside-gentoo/contact/">contact us</a>.
343 + <p class="mt-2"><a href="https://gitweb.gentoo.org/proj/gentoo-mirrorstats.git/">Gentoo Mirrorstats</a></p>
344 + </div>
345 + </div>
346 + <div class="row">
347 + <div class="col-2 col-sm-3 col-md-2">
348 + <ul class="footerlinks three-icons">
349 + <li><a href="https://twitter.com/gentoo" title="@Gentoo on Twitter"><span class="fa fa-twitter fa-fw"></span></a></li>
350 + <li><a href="https://www.facebook.com/gentoo.org" title="Gentoo on Facebook"><span class="fa fa-facebook fa-fw"></span></a></li>
351 + <li><a href="https://www.reddit.com/r/Gentoo/" title="Gentoo on Reddit"><span class="fa fa-reddit-alien fa-fw"></span></a></li>
352 + </ul>
353 + </div>
354 + <div class="col-10 col-sm-9 col-md-10">
355 + <strong>© 2001–2020 Gentoo Foundation, Inc.</strong><br>
356 + <small>
357 + Gentoo is a trademark of the Gentoo Foundation, Inc.
358 + The contents of this document, unless otherwise expressly stated, are licensed under the
359 + <a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license">CC-BY-SA-4.0</a> license.
360 + The <a href="https://www.gentoo.org/inside-gentoo/foundation/name-logo-guidelines.html">Gentoo Name and Logo Usage Guidelines</a> apply.
361 + </small>
362 + </div>
363 + </div>
364 + </div>
365 + </footer>
366 +
367 +
368 + <script src="https://assets.gentoo.org/tyrian/v2/jquery-3.3.slim.js"></script>
369 + <script src="https://assets.gentoo.org/tyrian/v2/popper.min.js"></script>
370 + <script src="https://assets.gentoo.org/tyrian/v2/bootstrap.min.js"></script>
371 +
372 +
373 + </body>
374 +</html>
375
376 diff --git a/html/stats.jinja2 b/html/stats.jinja2
377 new file mode 100644
378 index 0000000..e13cd45
379 --- /dev/null
380 +++ b/html/stats.jinja2
381 @@ -0,0 +1,339 @@
382 +<!DOCTYPE html>
383 +<html>
384 + <head>
385 + <title>Gentoo Mirrorstats</title>
386 + <meta charset="utf-8">
387 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
388 + <link href="https://assets.gentoo.org/tyrian/v2/tyrian.min.css" rel="stylesheet" media="screen">
389 + <link href="https://www.gentoo.org/assets/css/leaflet.css" rel="stylesheet" media="screen">
390 + <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.20/datatables.min.css"/>
391 + <link rel="icon" href="https://www.gentoo.org/favicon.ico" type="image/x-icon">
392 + </head>
393 +
394 + <body>
395 +
396 + <header>
397 + <div class="site-title">
398 + <div class="container">
399 + <div class="row justify-content-between">
400 + <div class="logo">
401 + <a href="/" title="Back to the homepage" class="site-logo">
402 + <img src="https://assets.gentoo.org/tyrian/site-logo.png" alt="Gentoo" srcset="https://assets.gentoo.org/tyrian/v2/site-logo.svg">
403 + </a>
404 + <span class="site-label">Mirrorstats</span>
405 + </div>
406 + <div class="site-title-buttons">
407 + <div class="btn-group btn-group-sm">
408 + <a href="https://get.gentoo.org/" role="button" class="btn get-gentoo"><span class="fa fa-fw fa-download"></span> <strong>Get Gentoo!</strong></a>
409 + <div class="btn-group btn-group-sm">
410 + <a class="btn gentoo-org-sites dropdown-toggle" data-toggle="dropdown" data-target="#" href="#">
411 + <span class="fa fa-fw fa-map-o"></span> <span class="d-none d-sm-inline">gentoo.org sites</span> <span class="caret"></span>
412 + </a>
413 + <div class="dropdown-menu dropdown-menu-right">
414 + <a class="dropdown-item" href="https://www.gentoo.org/" title="Main Gentoo website"><span class="fa fa-home fa-fw"></span> gentoo.org</a>
415 + <a class="dropdown-item" href="https://wiki.gentoo.org/" title="Find and contribute documentation"><span class="fa fa-file-text-o fa-fw"></span> Wiki</a>
416 + <a class="dropdown-item" href="https://bugs.gentoo.org/" title="Report issues and find common issues"><span class="fa fa-bug fa-fw"></span> Bugs</a>
417 + <a class="dropdown-item" href="https://forums.gentoo.org/" title="Discuss with the community"><span class="fa fa-comments-o fa-fw"></span> Forums</a>
418 + <a class="dropdown-item" href="https://packages.gentoo.org/" title="Find software for your Gentoo"><span class="fa fa-hdd-o fa-fw"></span> Packages</a>
419 + <div class="dropdown-divider"></div>
420 + <a class="dropdown-item" href="https://planet.gentoo.org/" title="Find out what's going on in the developer community"><span class="fa fa-rss fa-fw"></span> Planet</a>
421 + <a class="dropdown-item" href="https://archives.gentoo.org/" title="Read up on past discussions"><span class="fa fa-archive fa-fw"></span> Archives</a>
422 + <a class="dropdown-item" href="https://sources.gentoo.org/" title="Browse our source code"><span class="fa fa-code fa-fw"></span> Sources</a>
423 + <div class="dropdown-divider"></div>
424 + <a class="dropdown-item" href="https://infra-status.gentoo.org/" title="Get updates on the services provided by Gentoo"><span class="fa fa-server fa-fw"></span> Infra Status</a>
425 + </div>
426 + </div>
427 + </div>
428 + </div>
429 + </div>
430 + </div>
431 + </div>
432 + <nav class="tyrian-navbar navbar navbar-dark navbar-expand-lg bg-primary" role="navigation">
433 + <div class="container">
434 + <div class="navbar-header">
435 + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-main-collapse" aria-controls="navbar-main-collapse" aria-expanded="false" aria-label="Toggle navigation">
436 + <span class="navbar-toggler-icon"></span>
437 + </button>
438 + </div>
439 + <div class="collapse navbar-collapse navbar-main-collapse" id="navbar-main-collapse">
440 + <ul class="navbar-nav mr-auto">
441 + <li class="nav-item {%if type == 'all'%}active{%endif%}"><a class="nav-link" href="all.html">Home</a></li>
442 + <li class="nav-item {%if type == 'rsync'%}active{%endif%}"><a class="nav-link" href="rsync.html">Rsync</a></li>
443 + <li class="nav-item {%if type == 'distfiles'%}active{%endif%}"><a class="nav-link" href="distfiles.html">Distfiles</a></li>
444 + <li class="nav-item {%if type == 'snapshots'%}active{%endif%}"><a class="nav-link" href="snapshots.html">Snapshots</a></li>
445 + <li class="nav-item {%if type == 'releases'%}active{%endif%}"><a class="nav-link" href="releases.html">Releases</a></li>
446 + <li class="nav-item {%if type == 'experimental'%}active{%endif%}"><a class="nav-link" href="experimental.html">Experimental</a></li>
447 + <li class="nav-item "><a class="nav-link" href="help.html">Help</a></li>
448 + </ul>
449 + </div>
450 + </div>
451 + </nav>
452 + </header>
453 +
454 +
455 + <div class="container">
456 + <div class="row">
457 + <div class="col-md-12">
458 + <h1 class="first-header">Gentoo {% if type != "all" %}{{ type[0]|upper}}{{type[1:]}}{%endif%} Mirrors
459 + {% if type != "all" %}
460 + <small class="ml-2 mt-2 float-right" style="font-size: 60%;">
461 + <a title="Json Data" class="mr-2 text-muted" href="/{{type}}/state.json"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" focusable="false" width="1em" height="1em" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24"><path d="M5 3h2v2H5v5a2 2 0 0 1-2 2a2 2 0 0 1 2 2v5h2v2H5c-1.07-.27-2-.9-2-2v-4a2 2 0 0 0-2-2H0v-2h1a2 2 0 0 0 2-2V5a2 2 0 0 1 2-2m14 0a2 2 0 0 1 2 2v4a2 2 0 0 0 2 2h1v2h-1a2 2 0 0 0-2 2v4a2 2 0 0 1-2 2h-2v-2h2v-5a2 2 0 0 1 2-2a2 2 0 0 1-2-2V5h-2V3h2m-7 12a1 1 0 0 1 1 1a1 1 0 0 1-1 1a1 1 0 0 1-1-1a1 1 0 0 1 1-1m-4 0a1 1 0 0 1 1 1a1 1 0 0 1-1 1a1 1 0 0 1-1-1a1 1 0 0 1 1-1m8 0a1 1 0 0 1 1 1a1 1 0 0 1-1 1a1 1 0 0 1-1-1a1 1 0 0 1 1-1z" fill="#777777"/></svg></a>
462 + <a title="Original Mirmon Page" class="text-muted" href="/{{type}}/"><i class="fa fa-bar-chart" aria-hidden="true"></i></a>
463 + </small>
464 + {% endif %}
465 + </h1>
466 +
467 +
468 + <p>
469 + Welcome to the Gentoo Linux <tt>mirrorstats</tt> system. Below you can see an overview of all Gentoo {% if type != "all" %}{{ type[0]|upper}}{{type[1:]}}{%endif%} mirrors.<br/>
470 + For more information about Gentoo mirrors, how to contribute a mirror or any problems please have a look at the <a href="help.html">help page</a>.
471 + </p>
472 + <div id="mirrorLocations" style="height: 500px; margin-bottom: 1em;"></div>
473 + </div>
474 +
475 + <div class="col-md-12 my-4">
476 + <table id="table_id" class="display table">
477 + <thead>
478 + <tr>
479 + <th>Host</th>
480 + {% if type == "all" %}<th>Type</th>{% endif %}
481 + <th>Protocol</th>
482 + <th class="statusHistory">Daily Stats</th>
483 + <th class="statusHistory">Probe Stats</th>
484 + <th style="text-align: right;">Last State</th>
485 + </tr>
486 + </thead>
487 + <tbody>
488 +
489 + {% for mirror in mirrors %}
490 + {% for stat in mirrors[mirror]['Stats'] %}
491 + <tr>
492 + <td>{{ mirror }}</td>
493 + {% if type == "all" %}<td>{{ stat['Type'] }}</td>{% endif %}
494 + <td>{{ stat['Protocol'] }}</td>
495 + <td>{{ stat['StateHistory'] }}</td>
496 + <td>{{ stat['ProbeHistory'] }}</td>
497 + <td style="text-align: right;">
498 + {% if stat['StatusLastProbe'] == "ok" %}
499 + <span class="badge badge-success">OK</span>
500 + {% elif stat['StatusLastProbe'] == "hangs" %}
501 + <span class="badge badge-danger">Hangs</span>
502 + {% elif stat['StatusLastProbe'] == "no_time" %}
503 + <span class="badge badge-danger">No Time</span>
504 + {% elif stat['StatusLastProbe'] == "site_not_found" %}
505 + <span class="badge badge-danger">Site Not Found</span>
506 + {% elif stat['StatusLastProbe'] == "'-1'" %}
507 + <span class="badge badge-danger">-1</span>
508 + {% else %}
509 + <span class="badge badge-warning">{{ stat['StatusLastProbe'] }}</span>
510 + {% endif %}
511 + </td>
512 + </tr>
513 + {% endfor %}
514 + {% endfor %}
515 +
516 + </tbody>
517 + </table>
518 +
519 + </div>
520 + </div>
521 + </div>
522 +
523 +
524 + <footer>
525 + <div class="container">
526 + <div class="row">
527 + <div class="col-12 offset-md-2 col-md-7">
528 + <h3 class="footerhead">Gentoo Mirrorstats</h3>
529 + <div class="row">
530 + <div class="col-xs-12 col-md-4">
531 + <span class="kk-group-header">Mirror Data as current of</span><br>{{ lastUpdate }}
532 + </div>
533 + <div class="col-xs-12 col-md-4">
534 + <span>Data powered by:</span><br><a href="http://www.staff.science.uu.nl/~penni101/mirmon/">Mirmon v2.11</a>
535 + </div>
536 + <div class="col-xs-12 col-md-4">
537 + </div>
538 + </div>
539 + </div>
540 + <div class="col-12 col-md-3">
541 + <h3 class="footerhead">Questions or comments?</h3>
542 + Please feel free to <a href="https://www.gentoo.org/inside-gentoo/contact/">contact us</a>.
543 + <p class="mt-2"><a href="https://gitweb.gentoo.org/proj/gentoo-mirrorstats.git/">Gentoo Mirrorstats</a></p>
544 + </div>
545 + </div>
546 + <div class="row">
547 + <div class="col-2 col-sm-3 col-md-2">
548 + <ul class="footerlinks three-icons">
549 + <li><a href="https://twitter.com/gentoo" title="@Gentoo on Twitter"><span class="fa fa-twitter fa-fw"></span></a></li>
550 + <li><a href="https://www.facebook.com/gentoo.org" title="Gentoo on Facebook"><span class="fa fa-facebook fa-fw"></span></a></li>
551 + <li><a href="https://www.reddit.com/r/Gentoo/" title="Gentoo on Reddit"><span class="fa fa-reddit-alien fa-fw"></span></a></li>
552 + </ul>
553 + </div>
554 + <div class="col-10 col-sm-9 col-md-10">
555 + <strong>© 2001–2020 Gentoo Foundation, Inc.</strong><br>
556 + <small>
557 + Gentoo is a trademark of the Gentoo Foundation, Inc.
558 + The contents of this document, unless otherwise expressly stated, are licensed under the
559 + <a href="https://creativecommons.org/licenses/by-sa/4.0/" rel="license">CC-BY-SA-4.0</a> license.
560 + The <a href="https://www.gentoo.org/inside-gentoo/foundation/name-logo-guidelines.html">Gentoo Name and Logo Usage Guidelines</a> apply.
561 + </small>
562 + </div>
563 + </div>
564 + </div>
565 + </footer>
566 +
567 + <script>
568 + var mirrorLocations = {{locations}};
569 + </script>
570 +
571 +
572 + <script src="https://assets.gentoo.org/tyrian/v2/jquery-3.3.slim.js"></script>
573 + <script src="https://assets.gentoo.org/tyrian/v2/popper.min.js"></script>
574 + <script src="https://assets.gentoo.org/tyrian/v2/bootstrap.min.js"></script>
575 +
576 + <script src="https://www.gentoo.org/assets/js/leaflet.js"></script>
577 +
578 + <script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.20/rg-1.1.1/datatables.min.js"></script>
579 +
580 + <script>
581 +
582 + $(function() {
583 + L.Icon.Default.imagePath = 'https://www.gentoo.org/assets/img/maps/';
584 + var map = L.map('mirrorLocations', { zoomAnimationThreshold: 9 } ).setView([30, 0], 2);
585 + var markers = {};
586 +
587 + map.addLayer(new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { minZoom: 2, maxZoom: 8, attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' }));
588 +
589 +
590 + var greenIcon = new L.Icon({
591 + iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png',
592 + shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
593 + iconSize: [25, 41],
594 + iconAnchor: [12, 41],
595 + popupAnchor: [1, -34],
596 + shadowSize: [41, 41]
597 + });
598 +
599 + var orangeIcon = new L.Icon({
600 + iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-gold.png',
601 + shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
602 + iconSize: [25, 41],
603 + iconAnchor: [12, 41],
604 + popupAnchor: [1, -34],
605 + shadowSize: [41, 41]
606 + });
607 +
608 + var redIcon = new L.Icon({
609 + iconUrl: 'https://cdn.rawgit.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png',
610 + shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
611 + iconSize: [25, 41],
612 + iconAnchor: [12, 41],
613 + popupAnchor: [1, -34],
614 + shadowSize: [41, 41]
615 + });
616 +
617 +
618 +
619 + $.each(mirrorLocations, function(index, mirror) {
620 + if(mirror.Location){
621 + lat = mirror.Location.split(",")[0];
622 + long = mirror.Location.split(",")[1];
623 +
624 + ok = 0;
625 + for (let i = 0; i < mirror.Stats.length; i++){
626 + if(mirror.Stats[i].StatusLastProbe == "ok"){
627 + ok++;
628 + }
629 + }
630 +
631 + if(ok == mirror.Stats.length){
632 + marker = L.marker([lat, long], {icon: greenIcon}).addTo(map);
633 + }else if(ok == 0){
634 + marker = L.marker([lat, long], {icon: redIcon}).addTo(map);
635 + }else{
636 + marker = L.marker([lat, long], {icon: orangeIcon}).addTo(map);
637 + }
638 +
639 + popupText = "<h4 class='mt-2'> " + mirror.Hostname + "</h4>";
640 +
641 + popupText += "<table class='table'><tr>{% if type == 'all' %}<th>Type</th>{% endif %}<th>Protocol</th><th>Probe History</th><th>Last Probe</th></tr>";
642 + for (let i = 0; i < mirror.Stats.length; i++){
643 + probeHistory = "";
644 + for (let j = 0; j < mirror.Stats[i].ProbeHistory.length; j++) {
645 + if(mirror.Stats[i].ProbeHistory[j] == "s"){
646 + probeHistory += '<i class="fa fa-fw fa-check" style="color:#28a745;" aria-hidden="true"></i>';
647 + }else{
648 + probeHistory += '<i class="fa fa-fw fa-times" style="color:#dc3545;" aria-hidden="true"></i>';
649 + }
650 + }
651 +
652 + lastProbeStatus = mirror.Stats[i].StatusLastProbe;
653 +
654 + if(lastProbeStatus == "ok"){
655 + lastProbeStatus = '<span class="badge badge-success">OK</span>';
656 + } else if(lastProbeStatus == "hangs"){
657 + lastProbeStatus = '<span class="badge badge-danger">Hangs</span>';
658 + } else if(lastProbeStatus == "no_time"){
659 + lastProbeStatus = '<span class="badge badge-danger">No Time</span>';
660 + } else if(lastProbeStatus == "site_not_found"){
661 + lastProbeStatus = '<span class="badge badge-danger">Site Not Found</span>';
662 + } else if(lastProbeStatus == "'-1'"){
663 + lastProbeStatus = '<span class="badge badge-danger">-1</span>';
664 + } else {
665 + lastProbeStatus = '<span class="badge badge-warning">' + lastProbeStatus + '</span>';
666 + }
667 +
668 + popupText += "<tr>{% if type == 'all' %}<td>" + mirror.Stats[i].Type + "</td>{% endif %}<td>" + mirror.Stats[i].Protocol + "</td><td>" + probeHistory + "</td><td>" + lastProbeStatus + "</td></tr>";
669 + }
670 + popupText += "</table>";
671 +
672 +
673 + marker.bindPopup(popupText, {
674 + minWidth : 500,
675 + maxWidth : 600,
676 + maxHeight : 260,
677 + });
678 +
679 + markers[index] = marker;
680 + }
681 + });
682 + });
683 + </script>
684 +
685 + <script>
686 +
687 + $(document).ready( function () {
688 + $('#table_id').DataTable({
689 + "autoWidth": true,
690 + "iDisplayLength": 25,
691 + // TODO Group by Region in future
692 + // rowGroup: {
693 + // dataSrc: 1
694 + // }
695 + "columnDefs": [
696 + {
697 + "render": function ( data, type, row ) {
698 + state_str = data.split("-")[data.split("-").length-1];
699 + result = "";
700 +
701 + for (let i = 0; i < state_str.length; i++){
702 + if(state_str[i] == 's'){
703 + result += '<i class="fa fa-check" style="color:#28a745;width:1rem;text-align:center;" aria-hidden="true"></i>\n';
704 + }else{
705 + result += '<i class="fa fa-times" style="color:#dc3545;width:1rem;text-align:center;" aria-hidden="true"></i>\n';
706 + }
707 + }
708 +
709 + return result;
710 + },
711 + "targets": "statusHistory"
712 + },
713 + ]
714 + });
715 + } );
716 +
717 + </script>
718 +
719 + </body>
720 +</html>