blob: 33e26f706db356bf5465a00310d344f8e3ece2e6 [file] [log] [blame]
Andy Bavier614af142020-08-07 14:49:56 -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
Andy Bavier614af142020-08-07 14:49:56 -07006
7import unittest
8import edge_monitoring_server as ems
9import datetime
10import pytz
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070011import json
12import time
13
14
15test_edge = {
Andy Bavier8a5c9872020-10-21 13:17:53 -070016 'name': 'ace-menlo-pixel',
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070017 'status': {
18 'control_plane': 'connected',
19 'user_plane': 'connected'
20 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -080021 'speedtest': {
22 'ping': {
23 'dns': {
24 'min': 2.0,
25 'avg': 4.0,
26 'max': 6.0,
27 'stddev': 1.0
28 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -070029 },
30 'iperf': {
31 'cluster': {
32 'downlink': 100.0,
33 'uplink': 10.0
34 }
Jeremy Ronquillof4200252021-02-13 16:11:04 -080035 }
36 },
Hyunsun Moon200eba52021-04-05 21:31:54 -070037 'signal_quality': {
38 'rsrq': 30,
39 'rsrp': 80
40 },
41 'last_update': time.time()
42}
43
44test_edge_status_only = {
45 'name': 'ace-menlo-pixel',
46 'status': {
47 'control_plane': 'connected',
48 'user_plane': 'connected'
49 },
Jeremy Ronquillof4200252021-02-13 16:11:04 -080050 'last_update': time.time()
51}
52
53test_edge_no_speedtest = {
54 'name': 'ace-menlo-pixel',
55 'status': {
56 'control_plane': 'connected',
57 'user_plane': 'connected'
58 },
Hyunsun Moon200eba52021-04-05 21:31:54 -070059 'signal_quality': {
60 'rsrq': 30,
61 'rsrp': 80
62 },
63 'last_update': time.time()
64}
65
66test_edge_no_signal_quality = {
67 'name': 'ace-menlo-pixel',
68 'status': {
69 'control_plane': 'connected',
70 'user_plane': 'connected'
71 },
72 'speedtest': {
73 'ping': {
74 'dns': {
75 'min': 2.0,
76 'avg': 4.0,
77 'max': 6.0,
78 'stddev': 1.0
79 }
Jeremy Ronquilloc7434622021-04-08 21:06:00 -070080 },
81 'iperf': {
82 'cluster': {
83 'downlink': 100.0,
84 'uplink': 10.0
85 }
Hyunsun Moon200eba52021-04-05 21:31:54 -070086 }
87 },
Hyunsun Moon5f237ec2020-09-29 14:45:52 -070088 'last_update': time.time()
89}
Andy Bavier614af142020-08-07 14:49:56 -070090
Jeremy Ronquilloc7434622021-04-08 21:06:00 -070091test_edge_no_iperf = {
92 'name': 'ace-menlo-pixel',
93 'status': {
94 'control_plane': 'connected',
95 'user_plane': 'connected'
96 },
97 'speedtest': {
98 'ping': {
99 'dns': {
100 'min': 2.0,
101 'avg': 4.0,
102 'max': 6.0,
103 'stddev': 1.0
104 }
105 }
106 },
107 'signal_quality': {
108 'rsrq': 30,
109 'rsrp': 80
110 },
111 'last_update': time.time()
112}
113
Andy Bavier614af142020-08-07 14:49:56 -0700114
115class MyEvent:
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700116 def __init__ (self, location = "", description = "", summary = "", start = None, end = None, all_day = False):
Andy Bavier614af142020-08-07 14:49:56 -0700117 self.location = location
118 self.description = description
119 self.summary = summary
120 self.start = start
121 self.end = end
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700122 self.all_day = all_day
Andy Bavier614af142020-08-07 14:49:56 -0700123
124class MyEventNoLoc:
125 def __init__ (self, description = "", summary = ""):
126 self.description = description
127 self.summary = summary
128
129
130class TestEdgeMonitoringServer(unittest.TestCase):
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700131 def setUp(self):
132 self.app = ems.app.test_client()
Hyunsun Moon200eba52021-04-05 21:31:54 -0700133 self.emulated_time = time.mktime(time.strptime("2021-04-05 00:00:00", "%Y-%m-%d %H:%M:%S"))
134 self.time_method = time.time
135 time.time = self._get_time
136
137 def tearDown(self):
138 time.time = self.time_method
139
140 def _get_time(self):
141 return self.emulated_time
142
143 def _assert_status_metrics_exist(self, data):
144 self.assertTrue('aetheredge_status_control_plane{name="ace-menlo-pixel"} 2.0' in data)
145 self.assertTrue('aetheredge_status_user_plane{name="ace-menlo-pixel"} 2.0' in data)
146 self.assertTrue('aetheredge_last_update{name="ace-menlo-pixel"}' in data)
147 self.assertTrue('aetheredge_connect_test_ok{name="ace-menlo-pixel"} 1.0' in data)
148 self.assertTrue('aetheredge_ping_test_ok{name="ace-menlo-pixel"} 1.0' in data)
149 self.assertTrue('aetheredge_e2e_tests_ok{name="ace-menlo-pixel"} 1.0' in data)
150 self.assertTrue('aetheredge_e2e_tests_down{name="ace-menlo-pixel"} 0.0' in data)
151
152 def _assert_speedtest_metrics_exist(self, data):
153 self.assertTrue('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"} 2.0' in data)
154 self.assertTrue('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"} 4.0' in data)
155 self.assertTrue('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"} 6.0' in data)
156 self.assertTrue('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"} 1.0' in data)
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700157 self.assertTrue('aetheredge_iperf_cluster_downlink_test{name="ace-menlo-pixel"} 100.0' in data)
158 self.assertTrue('aetheredge_iperf_cluster_uplink_test{name="ace-menlo-pixel"} 10.0' in data)
Hyunsun Moon200eba52021-04-05 21:31:54 -0700159
160 def _assert_signal_quality_metrics_exist(self, data):
161 self.assertTrue('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"} 30' in data)
162 self.assertTrue('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"} 80' in data)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700163
Andy Bavier614af142020-08-07 14:49:56 -0700164 def test_match_location(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700165 event = MyEvent(location = "ace-menlo-pixel-production")
166 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
167 event = MyEvent(location = "(Compute)-MP-1-Aether Production")
168 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700169
170 def test_match_description(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700171 event = MyEvent(description = "ace-menlo-pixel-production")
172 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
173 event = MyEvent(description = "(Compute)-MP-1-Aether Production")
174 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700175
176 def test_match_summary(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700177 event = MyEvent(summary = "ace-menlo-pixel-production")
178 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
179 event = MyEvent(summary = "(Compute)-MP-1-Aether Production")
180 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700181
182 def test_no_match(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700183 event = MyEvent(summary = "ace-menlo-pixel-production, (Compute)-MP-1-Aether Production")
184 self.assertFalse(ems.is_my_event(event, "ace-intel"))
Andy Bavier614af142020-08-07 14:49:56 -0700185 self.assertFalse(ems.is_my_event(event, "(Compute)-MP-1-Aether Staging"))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700186 self.assertFalse(ems.is_my_event(event, "ace-menlo"))
Andy Bavier614af142020-08-07 14:49:56 -0700187
188 def test_missing_field(self):
Andy Bavier8a5c9872020-10-21 13:17:53 -0700189 event = MyEventNoLoc(description = "(Compute)-MP-1-Aether Production")
190 self.assertTrue(ems.is_my_event(event, "ace-menlo-pixel"))
Andy Bavier614af142020-08-07 14:49:56 -0700191
192 def test_in_window(self):
193 events = []
194 now = datetime.datetime.now(pytz.utc)
195 events.append(MyEvent(location = "(Compute)-MP-1-Aether Production",
196 start = now - datetime.timedelta(hours=1),
197 end = now + datetime.timedelta(hours=1)))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700198 self.assertTrue(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
199 self.assertFalse(ems.in_maintenance_window(events, "ace-tucson", now))
Andy Bavier614af142020-08-07 14:49:56 -0700200
201 def test_not_in_window(self):
202 events = []
203 now = datetime.datetime.now(pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700204 events.append(MyEvent(location = "ace-menlo-pixel-production",
Andy Bavier614af142020-08-07 14:49:56 -0700205 start = now + datetime.timedelta(hours=1),
206 end = now + datetime.timedelta(hours=2)))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700207 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavier614af142020-08-07 14:49:56 -0700208
209 def test_no_events(self):
210 events = []
211 now = datetime.datetime.now(pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700212 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavier614af142020-08-07 14:49:56 -0700213
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700214 def test_all_day_events(self):
215 events = []
Andy Bavier8a5c9872020-10-21 13:17:53 -0700216 events.append(MyEvent(location = "ace-menlo-pixel-production",
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700217 start = datetime.datetime(2020, 9, 2, 0, 0),
218 end = datetime.datetime(2020, 9, 3, 0, 0),
219 all_day = True))
220
221 ems.process_all_day_events(events)
222
223 now = datetime.datetime(2020, 9, 2, 12, 0, tzinfo=pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700224 self.assertTrue(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700225
226 now = datetime.datetime(2020, 9, 3, 12, 0, tzinfo=pytz.utc)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700227 self.assertFalse(ems.in_maintenance_window(events, "ace-menlo-pixel", now))
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700228
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700229 def test_get_edges(self):
230 response = self.app.get('/edges')
231 data = json.loads(response.get_data(as_text=True))
232 self.assertEqual(len(data['edges']), 1)
Andy Bavier8a5c9872020-10-21 13:17:53 -0700233 self.assertEqual(data['edges'][0]['name'], 'ace-example')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700234
Andy Bavierf872e9a2021-03-22 12:06:25 -0700235 def test_create_and_delete_edge_legacy(self):
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700236 response = self.app.post('/edges', json=test_edge)
237 data = json.loads(response.get_data(as_text=True))
Andy Bavier8a5c9872020-10-21 13:17:53 -0700238 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700239
240 response = self.app.get('/edges')
241 data = json.loads(response.get_data(as_text=True))
242 self.assertEqual(len(data['edges']), 2)
243
Andy Baviere47157d2020-12-11 14:13:12 -0700244 response = self.app.get('/edges/metrics')
245 data = response.get_data(as_text=True)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700246 print(data)
Hyunsun Moon200eba52021-04-05 21:31:54 -0700247
248 self._assert_status_metrics_exist(data)
249 self._assert_speedtest_metrics_exist(data)
250 self._assert_signal_quality_metrics_exist(data)
Andy Baviere47157d2020-12-11 14:13:12 -0700251
Andy Bavier8a5c9872020-10-21 13:17:53 -0700252 response = self.app.delete('/edges/ace-menlo-pixel')
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700253 data = json.loads(response.get_data(as_text=True))
254 self.assertEqual(data['result'], True)
Andy Baviere47157d2020-12-11 14:13:12 -0700255
256 response = self.app.get('/edges/metrics')
257 data = response.get_data(as_text=True)
Andy Bavier5b4e28f2021-03-09 15:48:20 -0700258 print(data)
259 self.assertFalse('ace-menlo-pixel' in data)
Hyunsun Moon5f237ec2020-09-29 14:45:52 -0700260
261 response = self.app.get('/edges')
262 data = json.loads(response.get_data(as_text=True))
263 self.assertEqual(len(data['edges']), 1)
Andy Bavierc41cf0c2020-09-02 14:49:21 -0700264
Andy Bavierf872e9a2021-03-22 12:06:25 -0700265 def test_create_and_delete_edge(self):
266 response = self.app.post('/testresults', json=test_edge)
267 data = json.loads(response.get_data(as_text=True))
268 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
269
270 response = self.app.get('/edges')
271 data = json.loads(response.get_data(as_text=True))
272 self.assertEqual(len(data['edges']), 2)
273
274 response = self.app.get('/edges/metrics')
275 data = response.get_data(as_text=True)
276 print(data)
Hyunsun Moon200eba52021-04-05 21:31:54 -0700277
278 self._assert_status_metrics_exist(data)
279 self._assert_speedtest_metrics_exist(data)
280 self._assert_signal_quality_metrics_exist(data)
Andy Bavierf872e9a2021-03-22 12:06:25 -0700281
282 response = self.app.delete('/testresults/ace-menlo-pixel')
283 data = json.loads(response.get_data(as_text=True))
284 self.assertEqual(data['result'], True)
285
286 response = self.app.get('/edges/metrics')
287 data = response.get_data(as_text=True)
288 print(data)
289 self.assertFalse('ace-menlo-pixel' in data)
290
291 response = self.app.get('/edges')
292 data = json.loads(response.get_data(as_text=True))
293 self.assertEqual(len(data['edges']), 1)
Andy Bavier614af142020-08-07 14:49:56 -0700294
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800295 def test_create_and_delete_edge_speed_test(self):
296 response = self.app.post('/testresults', json=test_edge)
297 data = json.loads(response.get_data(as_text=True))
298 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
299
300 response = self.app.get('/edges/metrics')
301 data = response.get_data(as_text=True)
302 print(data)
303
Hyunsun Moon200eba52021-04-05 21:31:54 -0700304 self._assert_speedtest_metrics_exist(data)
305
306 response = self.app.delete('/testresults/ace-menlo-pixel')
307 data = json.loads(response.get_data(as_text=True))
308 self.assertEqual(data['result'], True)
309
310 def test_backwards_compatible_status_only(self):
311 response = self.app.post('/testresults', json=test_edge_status_only)
312 data = json.loads(response.get_data(as_text=True))
313 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
314
315 response = self.app.get('/edges/metrics')
316 data = response.get_data(as_text=True)
317 print(data)
318
319 self.assertFalse('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"}' in data)
320 self.assertFalse('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"}' in data)
321
322 self._assert_status_metrics_exist(data)
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800323
324 response = self.app.delete('/testresults/ace-menlo-pixel')
325 data = json.loads(response.get_data(as_text=True))
326 self.assertEqual(data['result'], True)
327
328 def test_backwards_compatible_no_speedtest(self):
329 response = self.app.post('/testresults', json=test_edge_no_speedtest)
330 data = json.loads(response.get_data(as_text=True))
331 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
332
333 response = self.app.get('/edges/metrics')
334 data = response.get_data(as_text=True)
335 print(data)
336
337 self.assertFalse('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"}' in data)
338 self.assertFalse('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"}' in data)
339 self.assertFalse('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"}' in data)
340 self.assertFalse('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"}' in data)
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700341 self.assertFalse('aetheredge_iperf_cluster_downlink_test{name="ace-menlo-pixel"}' in data)
342 self.assertFalse('aetheredge_iperf_cluster_uplink_test{name="ace-menlo-pixel"}' in data)
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800343
Hyunsun Moon200eba52021-04-05 21:31:54 -0700344 self._assert_status_metrics_exist(data)
345 self._assert_signal_quality_metrics_exist(data)
Jeremy Ronquillof4200252021-02-13 16:11:04 -0800346
347 response = self.app.delete('/testresults/ace-menlo-pixel')
348 data = json.loads(response.get_data(as_text=True))
349 self.assertEqual(data['result'], True)
350
Hyunsun Moon200eba52021-04-05 21:31:54 -0700351 def test_backwards_compatible_no_signal_quality(self):
352 response = self.app.post('/testresults', json=test_edge_no_signal_quality)
353 data = json.loads(response.get_data(as_text=True))
354 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
355
356 response = self.app.get('/edges/metrics')
357 data = response.get_data(as_text=True)
358 print(data)
359
360 self.assertFalse('aetheredge_signal_quality_rsrq{name="ace-menlo-pixel"}' in data)
361 self.assertFalse('aetheredge_signal_quality_rsrp{name="ace-menlo-pixel"}' in data)
362
363 self._assert_status_metrics_exist(data)
364 self._assert_speedtest_metrics_exist(data)
365
366 response = self.app.delete('/testresults/ace-menlo-pixel')
367 data = json.loads(response.get_data(as_text=True))
368 self.assertEqual(data['result'], True)
369
370 def test_timeout_stale_result(self):
371 response = self.app.post('/testresults', json=test_edge)
372 data = json.loads(response.get_data(as_text=True))
373 print(json.dumps(data, indent=2))
374
375 self.assertEqual(data['edge']['status']['control_plane'], 'connected')
376 self.assertEqual(data['edge']['status']['user_plane'], 'connected')
377 self.assertEqual(data['edge']['speedtest']['ping']['dns']['avg'], 4.0)
378 self.assertTrue('signal_quality' in data['edge'])
379
380 self.emulated_time += (ems.NO_RESULT_THRESHOLD + 1)
381
382 response = self.app.get('/edges/ace-menlo-pixel')
383 data = json.loads(response.get_data(as_text=True))
384 print(json.dumps(data, indent=2))
385
386 self.assertEqual(data['edge']['status']['control_plane'], 'no result')
387 self.assertEqual(data['edge']['status']['user_plane'], 'no result')
388 self.assertEqual(data['edge']['speedtest']['ping']['dns']['avg'], 0.0)
389 self.assertFalse('signal_quality' in data['edge'])
390
Jeremy Ronquilloc7434622021-04-08 21:06:00 -0700391 def test_backwards_compatible_no_iperf(self):
392 response = self.app.post('/testresults', json=test_edge_no_iperf)
393 data = json.loads(response.get_data(as_text=True))
394 self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
395
396 response = self.app.get('/edges/metrics')
397 data = response.get_data(as_text=True)
398 print(data)
399
400 self.assertFalse('iperf_cluster_downlink{name="ace-menlo-pixel"}' in data)
401 self.assertFalse('iperf_cluster_uplink{name="ace-menlo-pixel"}' in data)
402
403 response = self.app.delete('/testresults/ace-menlo-pixel')
404 data = json.loads(response.get_data(as_text=True))
405 self.assertEqual(data['result'], True)
406
Hyunsun Moon200eba52021-04-05 21:31:54 -0700407
Andy Bavier614af142020-08-07 14:49:56 -0700408if __name__ == '__main__':
409 suite = unittest.TestLoader().loadTestsFromTestCase(TestEdgeMonitoringServer)
410 unittest.TextTestRunner(verbosity=2).run(suite)