blob: f9184d828dc070bf3cfe9d2064c929caf1bfeb10 [file] [log] [blame]
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -07001#!/usr/bin/env python
2
3# Copyright 2020-present Open Networking Foundation
4#
Hyunsun Moon200eba52021-04-05 21:31:54 -07005# SPDX-License-Identifier: LicenseRef-ONF-Member-Only-1.0
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -07006
Andy Bavier614af142020-08-07 14:49:56 -07007import os
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -07008import time
Andy Bavier614af142020-08-07 14:49:56 -07009import datetime
10import pytz
11import threading
12from icalevents.icalevents import events
Andy Bavier4021a2f2020-07-29 12:39:47 -070013from flask import Flask, jsonify, abort, request, Response
14import prometheus_client as prom
Andy Bavier2d60fc52021-05-04 16:13:39 -070015import jsonschema
Andy Bavier55dc5872021-05-05 11:31:42 -070016from logging.config import dictConfig
Andy Bavier4021a2f2020-07-29 12:39:47 -070017
Andy Bavier8a5c9872020-10-21 13:17:53 -070018# URL of maintenance calendar
Andy Bavier614af142020-08-07 14:49:56 -070019SECRET_ICAL_URL = os.environ.get("SECRET_ICAL_URL")
Andy Bavier8a5c9872020-10-21 13:17:53 -070020
21# Aether environment that the server is monitoring (e.g., "production")
22# To schedule downtime, postfix the cluster name with the env: "ace-tucson-production"
23AETHER_ENV = os.environ.get("AETHER_ENV", "production")
24
25# Move to "no result" status if we don't hear from agent for this many seconds
Andy Bavier4021a2f2020-07-29 12:39:47 -070026NO_RESULT_THRESHOLD = 720
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070027
Andy Bavier55dc5872021-05-05 11:31:42 -070028dictConfig({
29 'version': 1,
30 'formatters': {'default': {
Andy Bavier41fef772021-05-12 13:48:42 -070031 'format': '%(levelname)s %(message)s',
Andy Bavier55dc5872021-05-05 11:31:42 -070032 }},
33 'handlers': {'wsgi': {
34 'class': 'logging.StreamHandler',
35 'stream': 'ext://flask.logging.wsgi_errors_stream',
36 'formatter': 'default'
37 }},
38 'root': {
39 'level': 'INFO',
40 'handlers': ['wsgi']
41 }
42})
43
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -070044app = Flask(__name__)
Andy Bavier2d60fc52021-05-04 16:13:39 -070045
46edgeSchema = {
47 "type": "object",
48 "properties": {
49 "name": {"type": "string"},
50 "status": {
51 "type": "object",
52 "properties": {
53 "control_plane": {"type": "string"},
54 "user_plane": {"type": "string"}
55 },
56 "required": ["control_plane", "user_plane"]
57 },
58 "speedtest": {
59 "type": "object",
60 "properties": {
61 "ping": {
62 "type": "object",
63 "properties": {
64 "dns": {
65 "type": "object",
66 "properties": {
67 "min": {"type": "number"},
68 "avg": {"type": "number"},
69 "max": {"type": "number"},
70 "stddev": {"type": "number"}
71 },
72 "required": ["min", "avg", "max", "stddev"]
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -070073 },
74 "iperf_server": {
75 "type": "object",
76 "properties": {
77 "min": {"type": "number"},
78 "avg": {"type": "number"},
79 "max": {"type": "number"},
80 "stddev": {"type": "number"}
81 },
82 "required": ["min", "avg", "max", "stddev"]
Andy Bavier2d60fc52021-05-04 16:13:39 -070083 }
84 }
85 },
86 "iperf": {
87 "type": "object",
88 "properties": {
89 "cluster": {
90 "type": "object",
91 "properties": {
92 "downlink": {"type": "number"},
93 "uplink": {"type": "number"}
94 },
95 "required": ["downlink", "uplink"]
96 }
97 }
98 }
99 }
100 },
101 "signal_quality": {
102 "type": "object",
103 "properties": {
104 "rsrq": {"type": "number"},
105 "rsrp": {"type": "number"}
106 },
107 "required": ["rsrq", "rsrp"]
108 }
109 },
110 "required": ["name", "status"]
111}
112
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700113edges = [
114 {
Andy Bavier8a5c9872020-10-21 13:17:53 -0700115 'name': 'ace-example',
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700116 'status': {
117 'control_plane': 'connected',
118 'user_plane': 'connected'
119 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800120 'speedtest': {
121 'ping': {
122 'dns': {
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700123 'min': 0.0,
124 'avg': 0.0,
125 'max': 0.0,
126 'stddev': 0.0
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700127 },
128 'iperf_server': {
129 'min': 0.0,
130 'avg': 0.0,
131 'max': 0.0,
132 'stddev': 0.0
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800133 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700134 },
135 'iperf': {
136 'cluster': {
137 'downlink': 0.0,
138 'uplink': 0.0
139 }
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800140 }
141 },
Hyunsun Moon200eba52021-04-05 21:31:54 -0700142 'signal_quality': {
143 'rsrq': 0,
144 'rsrp': 0
145 },
146 'last_update': time.time()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700147 }
148]
149
Andy Bavier4021a2f2020-07-29 12:39:47 -0700150status_codes = {
151 "no result": -2,
152 "error": -1,
153 "disconnected": 0,
154 "connecting": 1,
155 "connected": 2
156}
157
Andy Bavier614af142020-08-07 14:49:56 -0700158room_mapping = {
Andy Baviere4591222021-07-07 12:44:19 -0700159 "ace-menlo-rasp-pi-production": "(Compute)-MP-1-Aether Production",
Andy Bavier0423cbd2020-10-23 10:50:29 -0700160 "ace-menlo-staging": "(Compute)-MP-1-Aether Staging"
Andy Bavier614af142020-08-07 14:49:56 -0700161}
162
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700163# Legacy test status metrics, reporting a status code between -2 and 2
Andy Bavier4021a2f2020-07-29 12:39:47 -0700164cp_status = prom.Gauge("aetheredge_status_control_plane", "Control plane status code", ["name"])
165up_status = prom.Gauge("aetheredge_status_user_plane", "User plane status code", ["name"])
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700166
167# Simplified binary test result metrics
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700168e2e_tests_ok = prom.Gauge("aetheredge_e2e_tests_ok", "Last connect and ping test both passed", ["name"])
Andy Baviera0c40aa2021-03-10 12:09:12 -0700169connect_test_ok = prom.Gauge("aetheredge_connect_test_ok", "Last connect test passed", ["name"])
Andy Baviera0c40aa2021-03-10 12:09:12 -0700170ping_test_ok = prom.Gauge("aetheredge_ping_test_ok", "Last ping test passed", ["name"])
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700171e2e_tests_down = prom.Gauge("aetheredge_e2e_tests_down", "E2E tests not reporting", ["name"])
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700172
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700173# Speedtest dns ping metrics
174ping_dns_min = prom.Gauge("aetheredge_ping_dns_test_min","Last ping test to dns minimum value",["name"])
175ping_dns_avg = prom.Gauge("aetheredge_ping_dns_test_avg","Last ping test to dns average",["name"])
176ping_dns_max = prom.Gauge("aetheredge_ping_dns_test_max","Last ping test to dns maximum value",["name"])
177ping_dns_stddev = prom.Gauge("aetheredge_ping_dns_test_stddev","Last ping test to dns standard deviation",["name"])
178
179# Speedtest iperf server ping metrics
180ping_iperf_server_min = prom.Gauge("aetheredge_ping_iperf_server_test_min","Last ping test to iperf_server minimum value",["name"])
181ping_iperf_server_avg = prom.Gauge("aetheredge_ping_iperf_server_test_avg","Last ping test to iperf_server average",["name"])
182ping_iperf_server_max = prom.Gauge("aetheredge_ping_iperf_server_test_max","Last ping test to iperf_server maximum value",["name"])
183ping_iperf_server_stddev = prom.Gauge("aetheredge_ping_iperf_server_test_stddev","Last ping test to iperf_server standard deviation",["name"])
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800184
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700185# Speedtest iperf metrics
186iperf_cluster_downlink = prom.Gauge("aetheredge_iperf_cluster_downlink_test","Last iperf test downlink result",["name"])
187iperf_cluster_uplink = prom.Gauge("aetheredge_iperf_cluster_uplink_test","Last iperf test downlink result",["name"])
188
Hyunsun Moon200eba52021-04-05 21:31:54 -0700189# Signal quality metrics in CESQ format not dB
190# RSRQ: >=53 excellent, 43 ~ 53 good, 33 ~ 43 mid, <=33 bad, 0 no signal
191# RSRP: >=20 excellent, 10 ~ 20 good, 0 ~ 10 mid, 0 no signal
192signal_quality_rsrq = prom.Gauge("aetheredge_signal_quality_rsrq", "Quality of the received signal", ["name"])
193signal_quality_rsrp = prom.Gauge("aetheredge_signal_quality_rsrp", "Power of the received signal", ["name"])
194
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700195# Other metrics
Andy Bavier4021a2f2020-07-29 12:39:47 -0700196last_update = prom.Gauge("aetheredge_last_update", "Last reported test result", ["name"])
Andy Bavier614af142020-08-07 14:49:56 -0700197maint_window = prom.Gauge("aetheredge_in_maintenance_window", "Currently in a maintenance window", ["name"])
198
199def is_my_event(event, name):
200 for field in ["summary", "location", "description"]:
Andy Bavier8a5c9872020-10-21 13:17:53 -0700201 fullname = name
202 if name.startswith("ace-"):
203 fullname = "%s-%s" % (name, AETHER_ENV)
204 if fullname in getattr(event, field, ""):
Andy Bavier614af142020-08-07 14:49:56 -0700205 return True
Andy Bavier0423cbd2020-10-23 10:50:29 -0700206 if fullname in room_mapping and room_mapping[fullname] in getattr(event, field, ""):
207 return True
Andy Bavier614af142020-08-07 14:49:56 -0700208 return False
209
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700210def is_naive_datetime(d):
211 return d.tzinfo is None or d.tzinfo.utcoffset(d) is None
212
213def process_all_day_events(es):
214 for event in es:
215 if event.all_day:
216 # All day events have naive datetimes, which breaks comparisons
217 pacific = pytz.timezone('US/Pacific')
218 if is_naive_datetime(event.start):
219 event.start = pacific.localize(event.start)
220 if is_naive_datetime(event.end):
221 event.end = pacific.localize(event.end)
222
Andy Bavier614af142020-08-07 14:49:56 -0700223def in_maintenance_window(events, name, now):
224 for event in events:
225 if event.start < now and event.end > now:
226 if is_my_event(event, name):
227 return True
Andy Bavier614af142020-08-07 14:49:56 -0700228 return False
229
230def pull_maintenance_events():
231 while(True):
232 now = datetime.datetime.now(pytz.utc)
233 try:
234 es = events(SECRET_ICAL_URL, start = now)
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700235 process_all_day_events(es)
Andy Bavier614af142020-08-07 14:49:56 -0700236 except Exception as e:
Andy Bavier55dc5872021-05-05 11:31:42 -0700237 app.logger.error(e)
Andy Bavier614af142020-08-07 14:49:56 -0700238 else:
239 for edge in edges:
240 if 'maintenance' not in edge:
241 edge['maintenance'] = {}
242 edge['maintenance']['in_window'] = in_maintenance_window(es, edge['name'], now)
243 edge['maintenance']['last_update'] = time.time()
244 time.sleep(60)
Andy Bavier4021a2f2020-07-29 12:39:47 -0700245
246def time_out_stale_results():
247 for edge in edges:
248 time_elapsed = time.time() - edge["last_update"]
249 if time_elapsed > NO_RESULT_THRESHOLD:
250 edge['status']['control_plane'] = "no result"
251 edge['status']['user_plane'] = "no result"
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700252 edge['speedtest']['ping']['dns'] = {'min': 0.0,
253 'avg': 0.0,
254 'max': 0.0,
255 'stddev': 0.0}
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700256 edge['speedtest']['ping']['iperf_server'] = {'min': 0.0,
257 'avg': 0.0,
258 'max': 0.0,
259 'stddev': 0.0}
Jeremy Ronquillo56b0a1e2021-04-09 00:26:18 -0700260 edge['speedtest']['iperf'] = {'cluster': {
261 'downlink': 0.0,
262 'uplink': 0.0
263 }
264 }
Hyunsun Moon200eba52021-04-05 21:31:54 -0700265 edge.pop('signal_quality', None)
Andy Bavier4021a2f2020-07-29 12:39:47 -0700266
Andy Baviere47157d2020-12-11 14:13:12 -0700267def remove_edge_from_metrics(name):
268 try:
269 cp_status.remove(name)
270 up_status.remove(name)
271 last_update.remove(name)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700272 e2e_tests_ok.remove(name)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700273 connect_test_ok.remove(name)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700274 ping_test_ok.remove(name)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700275 e2e_tests_down.remove(name)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700276 except:
277 pass
278
279 try:
Hyunsun Moon200eba52021-04-05 21:31:54 -0700280 ping_dns_min.remove(name)
281 ping_dns_avg.remove(name)
282 ping_dns_max.remove(name)
283 ping_dns_stddev.remove(name)
284 except:
285 pass
286
287 try:
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700288 ping_iperf_server_min.remove(name)
289 ping_iperf_server_avg.remove(name)
290 ping_iperf_server_max.remove(name)
291 ping_iperf_server_stddev.remove(name)
292 except:
293 pass
294
295 try:
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700296 iperf_cluster_downlink.remove(name)
297 iperf_cluster_uplink.remove(name)
298 except:
299 pass
300
301 try:
Hyunsun Moon200eba52021-04-05 21:31:54 -0700302 signal_quality_rsrq.remove(name)
303 signal_quality_rsrp.remove(name)
304 except:
305 pass
306
307 try:
Andy Baviere47157d2020-12-11 14:13:12 -0700308 maint_window.remove(name)
309 except:
310 pass
Andy Bavier4021a2f2020-07-29 12:39:47 -0700311
312@app.route('/edges/metrics', methods=['GET'])
313def get_prometheus_metrics():
314 res = []
315 time_out_stale_results()
316 for edge in edges:
Andy Bavier8a5c9872020-10-21 13:17:53 -0700317 if edge['name'] == "ace-example":
Andy Bavier4021a2f2020-07-29 12:39:47 -0700318 continue
319
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700320 connect_status = edge['status']['control_plane']
321 ping_status = edge['status']['user_plane']
322
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700323 # Add ping dns latency results if available
Jeremy Ronquillo5e559a82021-06-09 11:48:35 -0700324 try:
325 if edge['speedtest']['ping']['dns']['avg']:
326 ping_dns_min.labels(edge['name']).set(edge['speedtest']['ping']['dns']['min'])
327 ping_dns_avg.labels(edge['name']).set(edge['speedtest']['ping']['dns']['avg'])
328 ping_dns_max.labels(edge['name']).set(edge['speedtest']['ping']['dns']['max'])
329 ping_dns_stddev.labels(edge['name']).set(edge['speedtest']['ping']['dns']['stddev'])
330 except KeyError:
331 pass
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700332
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700333 # Add ping iperf_server latency results if available
Jeremy Ronquillo5e559a82021-06-09 11:48:35 -0700334 try:
335 if edge['speedtest']['ping']['iperf_server']['avg']:
336 ping_iperf_server_min.labels(edge['name']).set(edge['speedtest']['ping']['iperf_server']['min'])
337 ping_iperf_server_avg.labels(edge['name']).set(edge['speedtest']['ping']['iperf_server']['avg'])
338 ping_iperf_server_max.labels(edge['name']).set(edge['speedtest']['ping']['iperf_server']['max'])
339 ping_iperf_server_stddev.labels(edge['name']).set(edge['speedtest']['ping']['iperf_server']['stddev'])
340 except KeyError:
341 pass
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700342
343 # Add iperf bandwidth results if available
Jeremy Ronquillo5e559a82021-06-09 11:48:35 -0700344 try:
345 if edge['speedtest']['iperf']['cluster']['downlink']:
346 iperf_cluster_downlink.labels(edge['name']).set(edge['speedtest']['iperf']['cluster']['downlink'])
347 iperf_cluster_uplink.labels(edge['name']).set(edge['speedtest']['iperf']['cluster']['uplink'])
348 except KeyError:
349 pass
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800350
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700351 cp_status.labels(edge['name']).set(status_codes[connect_status])
352 up_status.labels(edge['name']).set(status_codes[ping_status])
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800353
Andy Bavier4021a2f2020-07-29 12:39:47 -0700354 last_update.labels(edge['name']).set(edge['last_update'])
Andy Bavier614af142020-08-07 14:49:56 -0700355 if 'maintenance' in edge:
356 maint_window.labels(edge['name']).set(int(edge['maintenance']['in_window']))
Andy Bavier4021a2f2020-07-29 12:39:47 -0700357
Andy Baviera0c40aa2021-03-10 12:09:12 -0700358 connect_test_ok.labels(edge['name']).set(0)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700359 ping_test_ok.labels(edge['name']).set(0)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700360 e2e_tests_ok.labels(edge['name']).set(0)
361 e2e_tests_down.labels(edge['name']).set(0)
362
363 if connect_status in ["error", "no result"] or ping_status in ["error", "no result"]:
364 e2e_tests_down.labels(edge['name']).set(1)
365 else:
366 if connect_status == "connected":
367 connect_test_ok.labels(edge['name']).set(1)
368 if ping_status == "connected":
369 ping_test_ok.labels(edge['name']).set(1)
370 if connect_status == "connected" and ping_status == "connected":
371 e2e_tests_ok.labels(edge['name']).set(1)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700372
Hyunsun Moon200eba52021-04-05 21:31:54 -0700373 if 'signal_quality' in edge.keys():
374 signal_quality_rsrq.labels(edge['name']).set(edge['signal_quality']['rsrq'])
375 signal_quality_rsrp.labels(edge['name']).set(edge['signal_quality']['rsrp'])
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800376
Andy Bavier4021a2f2020-07-29 12:39:47 -0700377 res.append(prom.generate_latest(cp_status))
378 res.append(prom.generate_latest(up_status))
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800379 res.append(prom.generate_latest(ping_dns_min))
380 res.append(prom.generate_latest(ping_dns_avg))
381 res.append(prom.generate_latest(ping_dns_max))
382 res.append(prom.generate_latest(ping_dns_stddev))
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700383 res.append(prom.generate_latest(ping_iperf_server_min))
384 res.append(prom.generate_latest(ping_iperf_server_avg))
385 res.append(prom.generate_latest(ping_iperf_server_max))
386 res.append(prom.generate_latest(ping_iperf_server_stddev))
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700387 res.append(prom.generate_latest(iperf_cluster_downlink))
388 res.append(prom.generate_latest(iperf_cluster_uplink))
Andy Bavier4021a2f2020-07-29 12:39:47 -0700389 res.append(prom.generate_latest(last_update))
Andy Bavier614af142020-08-07 14:49:56 -0700390 res.append(prom.generate_latest(maint_window))
Andy Baviera0c40aa2021-03-10 12:09:12 -0700391 res.append(prom.generate_latest(connect_test_ok))
Andy Baviera0c40aa2021-03-10 12:09:12 -0700392 res.append(prom.generate_latest(ping_test_ok))
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700393 res.append(prom.generate_latest(e2e_tests_ok))
394 res.append(prom.generate_latest(e2e_tests_down))
Hyunsun Moon200eba52021-04-05 21:31:54 -0700395 res.append(prom.generate_latest(signal_quality_rsrq))
396 res.append(prom.generate_latest(signal_quality_rsrp))
Andy Bavier614af142020-08-07 14:49:56 -0700397
Andy Bavier4021a2f2020-07-29 12:39:47 -0700398 return Response(res, mimetype="text/plain")
399
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700400
401@app.route('/edges/healthz', methods=['GET'])
402def get_health():
403 return {'message': 'healthy'}
404
405
406@app.route('/edges', methods=['GET'])
407def get_edges():
Andy Bavier4021a2f2020-07-29 12:39:47 -0700408 time_out_stale_results()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700409 return jsonify({'edges': edges})
410
411
412@app.route('/edges/<string:name>', methods=['GET'])
413def get_edge(name):
Andy Bavier4021a2f2020-07-29 12:39:47 -0700414 time_out_stale_results()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700415 edge = [edge for edge in edges if edge['name'] == name]
416 if len(edge) == 0:
417 abort(404)
418 return jsonify({'edge': edge[0]})
419
420
421@app.route('/edges', methods=['POST'])
Andy Bavierf872e9a2021-03-22 12:06:25 -0700422@app.route('/testresults', methods=['POST'])
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700423def create_or_update_edge():
Andy Bavier2d60fc52021-05-04 16:13:39 -0700424 try:
425 jsonschema.validate(instance=request.json, schema=edgeSchema)
426 except jsonschema.exceptions.ValidationError as err:
Andy Bavier55dc5872021-05-05 11:31:42 -0700427 app.logger.warn(err)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700428 abort(400)
429
430 req_edge = {
431 'name': request.json['name'],
432 'status': {
433 'control_plane': request.json['status']['control_plane'],
434 'user_plane': request.json['status']['user_plane']
435 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800436 'speedtest': {
437 'ping': {
438 'dns': {
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700439 'min': 0.0,
440 'avg': 0.0,
441 'max': 0.0,
442 'stddev': 0.0
Jeremy Ronquillo6e352b72021-06-08 10:33:25 -0700443 },
444 'iperf_server': {
445 'min': 0.0,
446 'avg': 0.0,
447 'max': 0.0,
448 'stddev': 0.0
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800449 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700450 },
451 'iperf': {
452 'cluster': {
453 'downlink': 0.0,
454 'uplink': 0.0
455 }
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800456 }
457 },
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700458 'last_update': time.time()
459 }
460
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800461 if 'speedtest' in request.json:
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700462 if 'ping' in request.json['speedtest']:
463 req_edge['speedtest']['ping'] = request.json['speedtest']['ping']
464 if 'iperf' in request.json['speedtest']:
465 req_edge['speedtest']['iperf'] = request.json['speedtest']['iperf']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800466
Hyunsun Moon200eba52021-04-05 21:31:54 -0700467 if 'signal_quality' in request.json:
468 req_edge['signal_quality'] = request.json['signal_quality']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800469
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700470 edge = [edge for edge in edges if edge['name'] == req_edge['name']]
471 if len(edge) == 0:
Andy Bavier55dc5872021-05-05 11:31:42 -0700472 app.logger.info("new edge request " + req_edge['name'])
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700473 edges.append(req_edge)
474 else:
475 edge[0]['status']['control_plane'] = req_edge['status']['control_plane']
476 edge[0]['status']['user_plane'] = req_edge['status']['user_plane']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800477 edge[0]['speedtest']['ping'] = req_edge['speedtest']['ping']
Jeremy Ronquillo56b0a1e2021-04-09 00:26:18 -0700478 edge[0]['speedtest']['iperf'] = req_edge['speedtest']['iperf']
Hyunsun Moon200eba52021-04-05 21:31:54 -0700479 if 'signal_quality' in req_edge.keys():
480 edge[0]['signal_quality'] = req_edge['signal_quality']
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700481 edge[0]['last_update'] = req_edge['last_update']
482
483 return jsonify({'edge': req_edge}), 201
484
485
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700486@app.route('/edges/<string:name>', methods=['DELETE'])
Andy Bavierf872e9a2021-03-22 12:06:25 -0700487@app.route('/testresults/<string:name>', methods=['DELETE'])
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700488def delete_edge(name):
Andy Bavier55dc5872021-05-05 11:31:42 -0700489 app.logger.info("delete edge request " + name)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700490 result = False
491 for i in range(len(edges)):
492 if edges[i]['name'] == name:
493 del edges[i]
Andy Baviere47157d2020-12-11 14:13:12 -0700494 remove_edge_from_metrics(name)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700495 result = True
496 break
497 if not result:
498 abort(404)
499 return jsonify({'result': True})
500
501
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700502if __name__ == '__main__':
Andy Bavier8a5c9872020-10-21 13:17:53 -0700503 if SECRET_ICAL_URL and AETHER_ENV:
Andy Bavier55dc5872021-05-05 11:31:42 -0700504 app.logger.info(" * Starting maintenance calendar polling thread (Aether env: %s)" % AETHER_ENV)
Andy Bavier614af142020-08-07 14:49:56 -0700505 t = threading.Thread(target=pull_maintenance_events)
506 t.start()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700507 app.run(debug=True, host='0.0.0.0', port=80)