blob: 6f74a53e7e8c6b7d19d59d92586d4c4977f047be [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': {
31 'format': '[%(asctime)s] %(levelname)s %(message)s',
32 }},
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"]
73 }
74 }
75 },
76 "iperf": {
77 "type": "object",
78 "properties": {
79 "cluster": {
80 "type": "object",
81 "properties": {
82 "downlink": {"type": "number"},
83 "uplink": {"type": "number"}
84 },
85 "required": ["downlink", "uplink"]
86 }
87 }
88 }
89 }
90 },
91 "signal_quality": {
92 "type": "object",
93 "properties": {
94 "rsrq": {"type": "number"},
95 "rsrp": {"type": "number"}
96 },
97 "required": ["rsrq", "rsrp"]
98 }
99 },
100 "required": ["name", "status"]
101}
102
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700103edges = [
104 {
Andy Bavier8a5c9872020-10-21 13:17:53 -0700105 'name': 'ace-example',
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700106 'status': {
107 'control_plane': 'connected',
108 'user_plane': 'connected'
109 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800110 'speedtest': {
111 'ping': {
112 'dns': {
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700113 'min': 0.0,
114 'avg': 0.0,
115 'max': 0.0,
116 'stddev': 0.0
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800117 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700118 },
119 'iperf': {
120 'cluster': {
121 'downlink': 0.0,
122 'uplink': 0.0
123 }
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800124 }
125 },
Hyunsun Moon200eba52021-04-05 21:31:54 -0700126 'signal_quality': {
127 'rsrq': 0,
128 'rsrp': 0
129 },
130 'last_update': time.time()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700131 }
132]
133
Andy Bavier4021a2f2020-07-29 12:39:47 -0700134status_codes = {
135 "no result": -2,
136 "error": -1,
137 "disconnected": 0,
138 "connecting": 1,
139 "connected": 2
140}
141
Andy Bavier614af142020-08-07 14:49:56 -0700142room_mapping = {
Andy Bavier0423cbd2020-10-23 10:50:29 -0700143 "ace-menlo-pixel-production": "(Compute)-MP-1-Aether Production",
144 "ace-menlo-staging": "(Compute)-MP-1-Aether Staging"
Andy Bavier614af142020-08-07 14:49:56 -0700145}
146
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700147# Legacy test status metrics, reporting a status code between -2 and 2
Andy Bavier4021a2f2020-07-29 12:39:47 -0700148cp_status = prom.Gauge("aetheredge_status_control_plane", "Control plane status code", ["name"])
149up_status = prom.Gauge("aetheredge_status_user_plane", "User plane status code", ["name"])
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700150
151# Simplified binary test result metrics
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700152e2e_tests_ok = prom.Gauge("aetheredge_e2e_tests_ok", "Last connect and ping test both passed", ["name"])
Andy Baviera0c40aa2021-03-10 12:09:12 -0700153connect_test_ok = prom.Gauge("aetheredge_connect_test_ok", "Last connect test passed", ["name"])
Andy Baviera0c40aa2021-03-10 12:09:12 -0700154ping_test_ok = prom.Gauge("aetheredge_ping_test_ok", "Last ping test passed", ["name"])
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700155e2e_tests_down = prom.Gauge("aetheredge_e2e_tests_down", "E2E tests not reporting", ["name"])
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700156
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700157# Speedtest ping metrics
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800158ping_dns_min = prom.Gauge("aetheredge_ping_dns_test_min","Last ping test minimum value",["name"])
159ping_dns_avg = prom.Gauge("aetheredge_ping_dns_test_avg","Last ping test average",["name"])
160ping_dns_max = prom.Gauge("aetheredge_ping_dns_test_max","Last ping test maximum value",["name"])
161ping_dns_stddev = prom.Gauge("aetheredge_ping_dns_test_stddev","Last ping test standard deviation",["name"])
162
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700163# Speedtest iperf metrics
164iperf_cluster_downlink = prom.Gauge("aetheredge_iperf_cluster_downlink_test","Last iperf test downlink result",["name"])
165iperf_cluster_uplink = prom.Gauge("aetheredge_iperf_cluster_uplink_test","Last iperf test downlink result",["name"])
166
Hyunsun Moon200eba52021-04-05 21:31:54 -0700167# Signal quality metrics in CESQ format not dB
168# RSRQ: >=53 excellent, 43 ~ 53 good, 33 ~ 43 mid, <=33 bad, 0 no signal
169# RSRP: >=20 excellent, 10 ~ 20 good, 0 ~ 10 mid, 0 no signal
170signal_quality_rsrq = prom.Gauge("aetheredge_signal_quality_rsrq", "Quality of the received signal", ["name"])
171signal_quality_rsrp = prom.Gauge("aetheredge_signal_quality_rsrp", "Power of the received signal", ["name"])
172
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700173# Other metrics
Andy Bavier4021a2f2020-07-29 12:39:47 -0700174last_update = prom.Gauge("aetheredge_last_update", "Last reported test result", ["name"])
Andy Bavier614af142020-08-07 14:49:56 -0700175maint_window = prom.Gauge("aetheredge_in_maintenance_window", "Currently in a maintenance window", ["name"])
176
177def is_my_event(event, name):
178 for field in ["summary", "location", "description"]:
Andy Bavier8a5c9872020-10-21 13:17:53 -0700179 fullname = name
180 if name.startswith("ace-"):
181 fullname = "%s-%s" % (name, AETHER_ENV)
182 if fullname in getattr(event, field, ""):
Andy Bavier614af142020-08-07 14:49:56 -0700183 return True
Andy Bavier0423cbd2020-10-23 10:50:29 -0700184 if fullname in room_mapping and room_mapping[fullname] in getattr(event, field, ""):
185 return True
Andy Bavier614af142020-08-07 14:49:56 -0700186 return False
187
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700188def is_naive_datetime(d):
189 return d.tzinfo is None or d.tzinfo.utcoffset(d) is None
190
191def process_all_day_events(es):
192 for event in es:
193 if event.all_day:
194 # All day events have naive datetimes, which breaks comparisons
195 pacific = pytz.timezone('US/Pacific')
196 if is_naive_datetime(event.start):
197 event.start = pacific.localize(event.start)
198 if is_naive_datetime(event.end):
199 event.end = pacific.localize(event.end)
200
Andy Bavier614af142020-08-07 14:49:56 -0700201def in_maintenance_window(events, name, now):
202 for event in events:
203 if event.start < now and event.end > now:
204 if is_my_event(event, name):
205 return True
Andy Bavier614af142020-08-07 14:49:56 -0700206 return False
207
208def pull_maintenance_events():
209 while(True):
210 now = datetime.datetime.now(pytz.utc)
211 try:
212 es = events(SECRET_ICAL_URL, start = now)
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700213 process_all_day_events(es)
Andy Bavier614af142020-08-07 14:49:56 -0700214 except Exception as e:
Andy Bavier55dc5872021-05-05 11:31:42 -0700215 app.logger.error(e)
Andy Bavier614af142020-08-07 14:49:56 -0700216 else:
217 for edge in edges:
218 if 'maintenance' not in edge:
219 edge['maintenance'] = {}
220 edge['maintenance']['in_window'] = in_maintenance_window(es, edge['name'], now)
221 edge['maintenance']['last_update'] = time.time()
222 time.sleep(60)
Andy Bavier4021a2f2020-07-29 12:39:47 -0700223
224def time_out_stale_results():
225 for edge in edges:
226 time_elapsed = time.time() - edge["last_update"]
227 if time_elapsed > NO_RESULT_THRESHOLD:
228 edge['status']['control_plane'] = "no result"
229 edge['status']['user_plane'] = "no result"
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700230 edge['speedtest']['ping']['dns'] = {'min': 0.0,
231 'avg': 0.0,
232 'max': 0.0,
233 'stddev': 0.0}
Jeremy Ronquillo56b0a1e2021-04-09 00:26:18 -0700234 edge['speedtest']['iperf'] = {'cluster': {
235 'downlink': 0.0,
236 'uplink': 0.0
237 }
238 }
Hyunsun Moon200eba52021-04-05 21:31:54 -0700239 edge.pop('signal_quality', None)
Andy Bavier4021a2f2020-07-29 12:39:47 -0700240
Andy Baviere47157d2020-12-11 14:13:12 -0700241def remove_edge_from_metrics(name):
242 try:
243 cp_status.remove(name)
244 up_status.remove(name)
245 last_update.remove(name)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700246 e2e_tests_ok.remove(name)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700247 connect_test_ok.remove(name)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700248 ping_test_ok.remove(name)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700249 e2e_tests_down.remove(name)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700250 except:
251 pass
252
253 try:
Hyunsun Moon200eba52021-04-05 21:31:54 -0700254 ping_dns_min.remove(name)
255 ping_dns_avg.remove(name)
256 ping_dns_max.remove(name)
257 ping_dns_stddev.remove(name)
258 except:
259 pass
260
261 try:
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700262 iperf_cluster_downlink.remove(name)
263 iperf_cluster_uplink.remove(name)
264 except:
265 pass
266
267 try:
Hyunsun Moon200eba52021-04-05 21:31:54 -0700268 signal_quality_rsrq.remove(name)
269 signal_quality_rsrp.remove(name)
270 except:
271 pass
272
273 try:
Andy Baviere47157d2020-12-11 14:13:12 -0700274 maint_window.remove(name)
275 except:
276 pass
Andy Bavier4021a2f2020-07-29 12:39:47 -0700277
278@app.route('/edges/metrics', methods=['GET'])
279def get_prometheus_metrics():
280 res = []
281 time_out_stale_results()
282 for edge in edges:
Andy Bavier8a5c9872020-10-21 13:17:53 -0700283 if edge['name'] == "ace-example":
Andy Bavier4021a2f2020-07-29 12:39:47 -0700284 continue
285
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700286 connect_status = edge['status']['control_plane']
287 ping_status = edge['status']['user_plane']
288
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700289 speedtest_ping_results_exist = True
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800290 if edge['speedtest']['ping']['dns']['avg']:
291 ping_dns_min_result = edge['speedtest']['ping']['dns']['min']
292 ping_dns_avg_result = edge['speedtest']['ping']['dns']['avg']
293 ping_dns_max_result = edge['speedtest']['ping']['dns']['max']
294 ping_dns_stddev_result = edge['speedtest']['ping']['dns']['stddev']
295 else:
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700296 speedtest_ping_results_exist = False
297
298 speedtest_iperf_results_exist = True
299 if edge['speedtest']['iperf']['cluster']['downlink']:
300 iperf_cluster_downlink_result = edge['speedtest']['iperf']['cluster']['downlink']
301 iperf_cluster_uplink_result = edge['speedtest']['iperf']['cluster']['uplink']
302 else:
303 speedtest_iperf_results_exist = False
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800304
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700305 cp_status.labels(edge['name']).set(status_codes[connect_status])
306 up_status.labels(edge['name']).set(status_codes[ping_status])
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800307
Andy Bavier4021a2f2020-07-29 12:39:47 -0700308 last_update.labels(edge['name']).set(edge['last_update'])
Andy Bavier614af142020-08-07 14:49:56 -0700309 if 'maintenance' in edge:
310 maint_window.labels(edge['name']).set(int(edge['maintenance']['in_window']))
Andy Bavier4021a2f2020-07-29 12:39:47 -0700311
Andy Baviera0c40aa2021-03-10 12:09:12 -0700312 connect_test_ok.labels(edge['name']).set(0)
Andy Baviera0c40aa2021-03-10 12:09:12 -0700313 ping_test_ok.labels(edge['name']).set(0)
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700314 e2e_tests_ok.labels(edge['name']).set(0)
315 e2e_tests_down.labels(edge['name']).set(0)
316
317 if connect_status in ["error", "no result"] or ping_status in ["error", "no result"]:
318 e2e_tests_down.labels(edge['name']).set(1)
319 else:
320 if connect_status == "connected":
321 connect_test_ok.labels(edge['name']).set(1)
322 if ping_status == "connected":
323 ping_test_ok.labels(edge['name']).set(1)
324 if connect_status == "connected" and ping_status == "connected":
325 e2e_tests_ok.labels(edge['name']).set(1)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700326
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700327 if speedtest_ping_results_exist:
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800328 ping_dns_min.labels(edge['name']).set(ping_dns_min_result)
329 ping_dns_avg.labels(edge['name']).set(ping_dns_avg_result)
330 ping_dns_max.labels(edge['name']).set(ping_dns_max_result)
331 ping_dns_stddev.labels(edge['name']).set(ping_dns_stddev_result)
332
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700333 if speedtest_iperf_results_exist:
334 iperf_cluster_downlink.labels(edge['name']).set(iperf_cluster_downlink_result)
335 iperf_cluster_uplink.labels(edge['name']).set(iperf_cluster_uplink_result)
336
Hyunsun Moon200eba52021-04-05 21:31:54 -0700337 if 'signal_quality' in edge.keys():
338 signal_quality_rsrq.labels(edge['name']).set(edge['signal_quality']['rsrq'])
339 signal_quality_rsrp.labels(edge['name']).set(edge['signal_quality']['rsrp'])
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800340
Andy Bavier4021a2f2020-07-29 12:39:47 -0700341 res.append(prom.generate_latest(cp_status))
342 res.append(prom.generate_latest(up_status))
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800343 res.append(prom.generate_latest(ping_dns_min))
344 res.append(prom.generate_latest(ping_dns_avg))
345 res.append(prom.generate_latest(ping_dns_max))
346 res.append(prom.generate_latest(ping_dns_stddev))
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700347 res.append(prom.generate_latest(iperf_cluster_downlink))
348 res.append(prom.generate_latest(iperf_cluster_uplink))
Andy Bavier4021a2f2020-07-29 12:39:47 -0700349 res.append(prom.generate_latest(last_update))
Andy Bavier614af142020-08-07 14:49:56 -0700350 res.append(prom.generate_latest(maint_window))
Andy Baviera0c40aa2021-03-10 12:09:12 -0700351 res.append(prom.generate_latest(connect_test_ok))
Andy Baviera0c40aa2021-03-10 12:09:12 -0700352 res.append(prom.generate_latest(ping_test_ok))
Andy Bavier3c7b78d2021-03-11 14:16:43 -0700353 res.append(prom.generate_latest(e2e_tests_ok))
354 res.append(prom.generate_latest(e2e_tests_down))
Hyunsun Moon200eba52021-04-05 21:31:54 -0700355 res.append(prom.generate_latest(signal_quality_rsrq))
356 res.append(prom.generate_latest(signal_quality_rsrp))
Andy Bavier614af142020-08-07 14:49:56 -0700357
Andy Bavier4021a2f2020-07-29 12:39:47 -0700358 return Response(res, mimetype="text/plain")
359
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700360
361@app.route('/edges/healthz', methods=['GET'])
362def get_health():
363 return {'message': 'healthy'}
364
365
366@app.route('/edges', methods=['GET'])
367def get_edges():
Andy Bavier4021a2f2020-07-29 12:39:47 -0700368 time_out_stale_results()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700369 return jsonify({'edges': edges})
370
371
372@app.route('/edges/<string:name>', methods=['GET'])
373def get_edge(name):
Andy Bavier4021a2f2020-07-29 12:39:47 -0700374 time_out_stale_results()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700375 edge = [edge for edge in edges if edge['name'] == name]
376 if len(edge) == 0:
377 abort(404)
378 return jsonify({'edge': edge[0]})
379
380
381@app.route('/edges', methods=['POST'])
Andy Bavierf872e9a2021-03-22 12:06:25 -0700382@app.route('/testresults', methods=['POST'])
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700383def create_or_update_edge():
Andy Bavier2d60fc52021-05-04 16:13:39 -0700384 try:
385 jsonschema.validate(instance=request.json, schema=edgeSchema)
386 except jsonschema.exceptions.ValidationError as err:
Andy Bavier55dc5872021-05-05 11:31:42 -0700387 app.logger.warn(err)
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700388 abort(400)
389
390 req_edge = {
391 'name': request.json['name'],
392 'status': {
393 'control_plane': request.json['status']['control_plane'],
394 'user_plane': request.json['status']['user_plane']
395 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800396 'speedtest': {
397 'ping': {
398 'dns': {
Jeremy Ronquilloa944fbc2021-03-30 10:57:45 -0700399 'min': 0.0,
400 'avg': 0.0,
401 'max': 0.0,
402 'stddev': 0.0
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800403 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700404 },
405 'iperf': {
406 'cluster': {
407 'downlink': 0.0,
408 'uplink': 0.0
409 }
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800410 }
411 },
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700412 'last_update': time.time()
413 }
414
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800415 if 'speedtest' in request.json:
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700416 if 'ping' in request.json['speedtest']:
417 req_edge['speedtest']['ping'] = request.json['speedtest']['ping']
418 if 'iperf' in request.json['speedtest']:
419 req_edge['speedtest']['iperf'] = request.json['speedtest']['iperf']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800420
Hyunsun Moon200eba52021-04-05 21:31:54 -0700421 if 'signal_quality' in request.json:
422 req_edge['signal_quality'] = request.json['signal_quality']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800423
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700424 edge = [edge for edge in edges if edge['name'] == req_edge['name']]
425 if len(edge) == 0:
Andy Bavier55dc5872021-05-05 11:31:42 -0700426 app.logger.info("new edge request " + req_edge['name'])
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700427 edges.append(req_edge)
428 else:
429 edge[0]['status']['control_plane'] = req_edge['status']['control_plane']
430 edge[0]['status']['user_plane'] = req_edge['status']['user_plane']
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800431 edge[0]['speedtest']['ping'] = req_edge['speedtest']['ping']
Jeremy Ronquillo56b0a1e2021-04-09 00:26:18 -0700432 edge[0]['speedtest']['iperf'] = req_edge['speedtest']['iperf']
Hyunsun Moon200eba52021-04-05 21:31:54 -0700433 if 'signal_quality' in req_edge.keys():
434 edge[0]['signal_quality'] = req_edge['signal_quality']
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700435 edge[0]['last_update'] = req_edge['last_update']
436
437 return jsonify({'edge': req_edge}), 201
438
439
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700440@app.route('/edges/<string:name>', methods=['DELETE'])
Andy Bavierf872e9a2021-03-22 12:06:25 -0700441@app.route('/testresults/<string:name>', methods=['DELETE'])
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700442def delete_edge(name):
Andy Bavier55dc5872021-05-05 11:31:42 -0700443 app.logger.info("delete edge request " + name)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700444 result = False
445 for i in range(len(edges)):
446 if edges[i]['name'] == name:
447 del edges[i]
Andy Baviere47157d2020-12-11 14:13:12 -0700448 remove_edge_from_metrics(name)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700449 result = True
450 break
451 if not result:
452 abort(404)
453 return jsonify({'result': True})
454
455
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700456if __name__ == '__main__':
Andy Bavier8a5c9872020-10-21 13:17:53 -0700457 if SECRET_ICAL_URL and AETHER_ENV:
Andy Bavier55dc5872021-05-05 11:31:42 -0700458 app.logger.info(" * Starting maintenance calendar polling thread (Aether env: %s)" % AETHER_ENV)
Andy Bavier614af142020-08-07 14:49:56 -0700459 t = threading.Thread(target=pull_maintenance_events)
460 t.start()
Hyunsun Moonf32ae9a2020-05-28 13:17:45 -0700461 app.run(debug=True, host='0.0.0.0', port=80)