[AETHER-1278]: Update Edge Monitoring Server to support speedtest results

Change-Id: If96add0506a07495d5648ffc3439263d0405cf8c
diff --git a/edge-monitoring/VERSION b/edge-monitoring/VERSION
index be14282..7d85683 100644
--- a/edge-monitoring/VERSION
+++ b/edge-monitoring/VERSION
@@ -1 +1 @@
-0.5.3
+0.5.4
diff --git a/edge-monitoring/edge_monitoring_server.py b/edge-monitoring/edge_monitoring_server.py
index 4b935c6..f7ec3db 100755
--- a/edge-monitoring/edge_monitoring_server.py
+++ b/edge-monitoring/edge_monitoring_server.py
@@ -41,6 +41,16 @@
             'control_plane': 'connected',
             'user_plane': 'connected'
         },
+        'speedtest': {
+            'ping': {
+                'dns': {
+                    'min': None,
+                    'avg': None,
+                    'max': None,
+                    'stddev': None
+                }
+            }
+        },
         'last_update': time.time(),
     }
 ]
@@ -68,6 +78,12 @@
 ping_test_ok = prom.Gauge("aetheredge_ping_test_ok", "Last ping test passed", ["name"])
 e2e_tests_down = prom.Gauge("aetheredge_e2e_tests_down", "E2E tests not reporting", ["name"])
 
+# Speedtest metrics
+ping_dns_min = prom.Gauge("aetheredge_ping_dns_test_min","Last ping test minimum value",["name"])
+ping_dns_avg = prom.Gauge("aetheredge_ping_dns_test_avg","Last ping test average",["name"])
+ping_dns_max = prom.Gauge("aetheredge_ping_dns_test_max","Last ping test maximum value",["name"])
+ping_dns_stddev = prom.Gauge("aetheredge_ping_dns_test_stddev","Last ping test standard deviation",["name"])
+
 # Other metrics
 last_update = prom.Gauge("aetheredge_last_update", "Last reported test result", ["name"])
 maint_window = prom.Gauge("aetheredge_in_maintenance_window", "Currently in a maintenance window", ["name"])
@@ -125,11 +141,19 @@
         if time_elapsed > NO_RESULT_THRESHOLD:
             edge['status']['control_plane'] = "no result"
             edge['status']['user_plane'] = "no result"
+            edge['speedtest']['ping']['dns'] = {'min': None,
+                                                'avg': None,
+                                                'max': None,
+                                                'stddev': None}
 
 def remove_edge_from_metrics(name):
     try:
         cp_status.remove(name)
         up_status.remove(name)
+        ping_dns_min.remove(name)
+        ping_dns_avg.remove(name)
+        ping_dns_max.remove(name)
+        ping_dns_stddev.remove(name)
         last_update.remove(name)
         e2e_tests_ok.remove(name)
         connect_test_ok.remove(name)
@@ -154,8 +178,18 @@
         connect_status = edge['status']['control_plane']
         ping_status = edge['status']['user_plane']
 
+        valid_speedtest_results = True
+        if edge['speedtest']['ping']['dns']['avg']:
+            ping_dns_min_result = edge['speedtest']['ping']['dns']['min']
+            ping_dns_avg_result = edge['speedtest']['ping']['dns']['avg']
+            ping_dns_max_result = edge['speedtest']['ping']['dns']['max']
+            ping_dns_stddev_result = edge['speedtest']['ping']['dns']['stddev']
+        else:
+            valid_speedtest_results = False
+
         cp_status.labels(edge['name']).set(status_codes[connect_status])
         up_status.labels(edge['name']).set(status_codes[ping_status])
+
         last_update.labels(edge['name']).set(edge['last_update'])
         if 'maintenance' in edge:
             maint_window.labels(edge['name']).set(int(edge['maintenance']['in_window']))
@@ -175,8 +209,19 @@
             if connect_status == "connected" and ping_status == "connected":
                 e2e_tests_ok.labels(edge['name']).set(1)
 
+        if valid_speedtest_results:
+            ping_dns_min.labels(edge['name']).set(ping_dns_min_result)
+            ping_dns_avg.labels(edge['name']).set(ping_dns_avg_result)
+            ping_dns_max.labels(edge['name']).set(ping_dns_max_result)
+            ping_dns_stddev.labels(edge['name']).set(ping_dns_stddev_result)
+
+
     res.append(prom.generate_latest(cp_status))
     res.append(prom.generate_latest(up_status))
+    res.append(prom.generate_latest(ping_dns_min))
+    res.append(prom.generate_latest(ping_dns_avg))
+    res.append(prom.generate_latest(ping_dns_max))
+    res.append(prom.generate_latest(ping_dns_stddev))
     res.append(prom.generate_latest(last_update))
     res.append(prom.generate_latest(maint_window))
     res.append(prom.generate_latest(connect_test_ok))
@@ -223,9 +268,25 @@
             'control_plane': request.json['status']['control_plane'],
             'user_plane': request.json['status']['user_plane']
         },
+        'speedtest': {
+            'ping': {
+                'dns': {
+                    'min': None,
+                    'avg': None,
+                    'max': None,
+                    'stddev': None
+                }
+            }
+        },
         'last_update': time.time()
     }
 
+    if 'speedtest' in request.json:
+        req_edge['speedtest'] = {
+            'ping': request.json['speedtest']['ping']
+        }
+
+
     edge = [edge for edge in edges if edge['name'] == req_edge['name']]
     if len(edge) == 0:
         print("new edge request " + req_edge['name'])
@@ -233,6 +294,7 @@
     else:
         edge[0]['status']['control_plane'] = req_edge['status']['control_plane']
         edge[0]['status']['user_plane'] = req_edge['status']['user_plane']
+        edge[0]['speedtest']['ping'] = req_edge['speedtest']['ping']
         edge[0]['last_update'] = req_edge['last_update']
 
     return jsonify({'edge': req_edge}), 201
diff --git a/edge-monitoring/test_edge_monitoring_server.py b/edge-monitoring/test_edge_monitoring_server.py
index 9aad259..a7e8cf2 100755
--- a/edge-monitoring/test_edge_monitoring_server.py
+++ b/edge-monitoring/test_edge_monitoring_server.py
@@ -28,6 +28,25 @@
         'control_plane': 'connected',
         'user_plane': 'connected'
     },
+    'speedtest': {
+        'ping': {
+            'dns': {
+                'min': 2.0,
+                'avg': 4.0,
+                'max': 6.0,
+                'stddev': 1.0
+            }
+        }
+    },
+    'last_update': time.time()
+}
+
+test_edge_no_speedtest = {
+    'name': 'ace-menlo-pixel',
+    'status': {
+        'control_plane': 'connected',
+        'user_plane': 'connected'
+    },
     'last_update': time.time()
 }
 
@@ -188,6 +207,50 @@
         data = json.loads(response.get_data(as_text=True))
         self.assertEqual(len(data['edges']), 1)
 
+    def test_create_and_delete_edge_speed_test(self):
+        response = self.app.post('/testresults', json=test_edge)
+        data = json.loads(response.get_data(as_text=True))
+        self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
+
+        response = self.app.get('/edges/metrics')
+        data = response.get_data(as_text=True)
+        print(data)
+
+        self.assertTrue('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"} ' + str(test_edge['speedtest']['ping']['dns']['min']) in data)
+        self.assertTrue('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"} ' + str(test_edge['speedtest']['ping']['dns']['avg']) in data)
+        self.assertTrue('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"} ' + str(test_edge['speedtest']['ping']['dns']['max']) in data)
+        self.assertTrue('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"} ' + str(test_edge['speedtest']['ping']['dns']['stddev']) in data)
+
+        response = self.app.delete('/testresults/ace-menlo-pixel')
+        data = json.loads(response.get_data(as_text=True))
+        self.assertEqual(data['result'], True)
+
+    def test_backwards_compatible_no_speedtest(self):
+        response = self.app.post('/testresults', json=test_edge_no_speedtest)
+        data = json.loads(response.get_data(as_text=True))
+        self.assertEqual(data['edge']['name'], 'ace-menlo-pixel')
+
+        response = self.app.get('/edges/metrics')
+        data = response.get_data(as_text=True)
+        print(data)
+
+        self.assertFalse('aetheredge_ping_dns_test_min{name="ace-menlo-pixel"}' in data)
+        self.assertFalse('aetheredge_ping_dns_test_avg{name="ace-menlo-pixel"}' in data)
+        self.assertFalse('aetheredge_ping_dns_test_max{name="ace-menlo-pixel"}' in data)
+        self.assertFalse('aetheredge_ping_dns_test_stddev{name="ace-menlo-pixel"}' in data)
+
+        self.assertTrue('aetheredge_status_control_plane{name="ace-menlo-pixel"} 2.0' in data)
+        self.assertTrue('aetheredge_status_user_plane{name="ace-menlo-pixel"} 2.0' in data)
+        self.assertTrue('aetheredge_last_update{name="ace-menlo-pixel"}' in data)
+        self.assertTrue('aetheredge_connect_test_ok{name="ace-menlo-pixel"} 1.0' in data)
+        self.assertTrue('aetheredge_ping_test_ok{name="ace-menlo-pixel"} 1.0' in data)
+        self.assertTrue('aetheredge_e2e_tests_ok{name="ace-menlo-pixel"} 1.0' in data)
+        self.assertTrue('aetheredge_e2e_tests_down{name="ace-menlo-pixel"} 0.0' in data)
+
+        response = self.app.delete('/testresults/ace-menlo-pixel')
+        data = json.loads(response.get_data(as_text=True))
+        self.assertEqual(data['result'], True)
+
 if __name__ == '__main__':
     suite = unittest.TestLoader().loadTestsFromTestCase(TestEdgeMonitoringServer)
     unittest.TextTestRunner(verbosity=2).run(suite)