Fetch secrets from env if set
Change-Id: I29ec0cfb182e64b40d28dcfad3f6e9b78f067c70
diff --git a/network-diag-app.py b/network-diag-app.py
new file mode 100644
index 0000000..d8c9002
--- /dev/null
+++ b/network-diag-app.py
@@ -0,0 +1,195 @@
+"""
+SPDX-FileCopyrightText: 2020-present Open Networking Foundation <info@opennetworking.org>
+SPDX-License-Identifier: LicenseRef-ONF-Member-1.01
+"""
+import sys
+import os
+from datetime import datetime
+
+from flask import Flask, request
+import logging as log
+from argparse import ArgumentParser, SUPPRESS
+import threading
+
+from roc import Roc
+from prom import Prometheus
+from ping import ping
+
+app = Flask(__name__)
+
+devices = {} # dict imsi:device
+lock = threading.Lock()
+probe_start = threading.Event()
+probe_stop = threading.Event()
+
+
+@app.route("/devices")
+def get_devices():
+ global devices, lock
+ with lock:
+ all = {}
+ for _, device in devices.items():
+ all[device.imsi_id] = {'ip': device.ip, 'imsi': device.imsi, 'last_reachable': '{:%Y-%m-%d %H:%M:%S}'.format(device.last_reachable)}
+ return all
+
+
+@app.route("/devices/reachable")
+def get_devices_reachable():
+ global devices, lock
+ with lock:
+ reachable = {}
+ for _, device in devices.items():
+ if device.reachable is True:
+ reachable[device.imsi_id] = {'ip': device.ip, 'imsi': device.imsi, 'last_reachable': '{:%Y-%m-%d %H:%M:%S}'.format(device.last_reachable)}
+ return reachable
+
+
+@app.route("/devices/unreachable")
+def get_devices_unreachable():
+ global devices, lock
+ with lock:
+ unreachable = {}
+ for _, device in devices.items():
+ if device.reachable is False:
+ unreachable[device.imsi_id] = {'ip': device.ip, 'imsi': device.imsi, 'last_reachable': '{:%Y-%m-%d %H:%M:%S}'.format(device.last_reachable)}
+ return unreachable
+
+
+@app.route("/probe")
+def probe():
+ update_and_probe()
+ return get_devices_reachable()
+
+
+# curl http://localhost:3333/config?period=0
+@app.route("/config")
+def config():
+ global args, probe_stop
+ period = request.args.get('period')
+ if period is not None:
+ period = int(period)
+ if period == 0:
+ log.info("Stopping probes...")
+ args.period = period
+ probe_stop.set()
+ else:
+ log.info("Starting probes...")
+ args.period = period
+ probe_start.set()
+ config = vars(args)
+ config.pop('token', None)
+ config.pop('user', None)
+ config.pop('password', None)
+ return config
+
+
+def build_argparser():
+ parser = ArgumentParser(add_help=False)
+ args = parser.add_argument_group('Options')
+ args.add_argument('-h', '--help',
+ action='help',
+ default=SUPPRESS,
+ help='Show this help message and exit.')
+ args.add_argument("--user",
+ help="ROC username",
+ type=str)
+ args.add_argument("--password",
+ help="ROC password",
+ type=str)
+ args.add_argument("--token",
+ help="Rancher bearer token",
+ type=str)
+ args.add_argument("--port",
+ help="Service port",
+ type=str,
+ default="3333")
+ args.add_argument("--period",
+ help="Probing period in sec",
+ type=int,
+ default=180)
+ args.add_argument("--url",
+ help="ROC url",
+ type=str,
+ default="https://roc.menlo.aetherproject.org/aether-roc-api/aether/v2.0.0/connectivity-service-v2/")
+ args.add_argument("--enterprise",
+ help="Enterprise Id",
+ type=str,
+ default="aether-onf")
+ args.add_argument("--site",
+ help="Site Id",
+ type=str,
+ default="menlo-4g")
+ return parser
+
+
+def update(roc, prom, old):
+ new = roc.update_devices(old)
+ if new is not None:
+ new = prom.update_devices(new)
+ else:
+ new = old
+ return new
+
+
+def do_probe(devices):
+ for imsi_id, device in devices.items():
+ if device.ip is None:
+ continue
+ if ping(device.ip):
+ device.reachable = True
+ device.last_reachable = datetime.now()
+ log.info("{}/{}/{} - reachable".format(device.imsi_id, device.imsi, device.ip))
+ else:
+ device.reachable = False
+ log.info("{}/{}/{} - unreachable".format(device.imsi_id, device.imsi, device.ip))
+
+
+def update_and_probe():
+ global devices, lock
+ new = update(roc, prom, devices)
+ do_probe(new)
+ with lock:
+ devices = new
+
+
+def work_thread(roc, prom):
+ global args
+ while True:
+ probe_start.wait()
+ probe_start.clear()
+ log.info("Probing started")
+ while True:
+ update_and_probe()
+ if probe_stop.wait(timeout=args.period):
+ log.info("Probing stopped")
+ probe_stop.clear()
+ break
+
+
+if __name__ == '__main__':
+
+ log.basicConfig(
+ format='%(asctime)s %(levelname)-8s %(message)s',
+ level=log.DEBUG,
+ datefmt='%Y-%m-%d %H:%M:%S',
+ stream=sys.stdout)
+
+ log.info("Starting network-diag-app...")
+
+ args = build_argparser().parse_args()
+
+ if not args.user:
+ args.user = os.environ.get('ROCUSER')
+ if not args.password:
+ args.password = os.environ.get('ROCPASSWORD')
+ if not args.token:
+ args.token= os.environ.get('KEYCLOAKTOKEN')
+
+ roc = Roc(args.url, args.user, args.password, args.enterprise, args.site)
+ prom = Prometheus(args.token.split(':')[0], args.token.split(':')[1])
+
+ t = threading.Thread(target=work_thread, args=(roc, prom,))
+ t.start()
+ probe_start.set()
+
+ app.run('0.0.0.0', args.port)