Renew ROC api key

Change-Id: Ieaf4ffd83a3cf6ea47071578fd48bbfd5da308be
diff --git a/Makefile b/Makefile
index 08e84a3..4341efd 100644
--- a/Makefile
+++ b/Makefile
@@ -78,7 +78,7 @@
 		--network host \
 		--name $(CONTAINER_NAME) \
 		--rm \
-		$(DOCKER_IMAGENAME) --key "eyJhbGciOiJSUzI1NiIsImtpZCI6IjUwNDJmNjcxYTQ1YWMxNGM1MzA0ZTA3MWY3MWM2N2FkNGE4N2RhZDYifQ.eyJpc3MiOiJodHRwczovL2RleC5hZXRoZXJwcm9qZWN0Lm9yZy9kZXgiLCJzdWIiOiJDaXN4TmpNNE5ERTZPRGMxWlRNeU5qY3RZakkwT1MwME9XTXdMV0V5TW1ZdE1qUmlaalUyWXprNVpEazFFZ1ZqY205M1pBIiwiYXVkIjoiYWV0aGVyLXJvYy1ndWkiLCJleHAiOjE2Mzg5OTU0MTAsImlhdCI6MTYzODkwOTAxMCwibm9uY2UiOiJNSGRTV25CWFpGRkxRVmxNWlROWk9IbzViWE55ZDJOV2VFWnlTV2RuUlRSUE4xaDNTMnBSTVV4NGRUSmoiLCJhdF9oYXNoIjoiWGtGNW5WM3UwcUZxYml3RC03c2NNdyIsImNfaGFzaCI6ImUzdXdRVkZpOW5ieGJlbHNmNW9MS0EiLCJlbWFpbCI6InNoYWRAb3Blbm5ldHdvcmtpbmcub3JnIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImdyb3VwcyI6WyJBZXRoZXJST0NBZG1pbiIsIk9ORlN0YWZmIl0sIm5hbWUiOiJzaGFkIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic2hhZCJ9.uIaSeuJGviVSiQeOT8EBPBoLBDy5G8lSwXz48XoAyNIyj3jontKNKfOf8pnQR7Cvrutqk56WOS78V8HPQgr01uTezaSHMZzPNnHtsyyCreMChAwKV-ZKS40b0q56yNihScHHVB0wlSO6Yr9K45M2tX1AActL10Ky3td9myvObPXEPgYsiG-KTWQVNAC_dnrmArKuUiqVlWAJhJckdRBOGHVhceenaDCrMPB8u-Z3_-S89gq4mper1fXNFmDCxXbRceJJPfWeWJNhJEQ0y1LC1c8JLxKFpynjfetXCA9qAaPJ0vzn-NYQnVpTqiDm7BsW4Ry1-62Nlgm3km2wT-Le_A"
+		$(DOCKER_IMAGENAME) --user "user" --password "password"
 
 run-native-file: $(VENV)
 	. ./bin/person_detection.sh -i ./resources/run.mp4
diff --git a/person_detection/app.py b/person_detection/app.py
index b1e9b2d..0ed28eb 100644
--- a/person_detection/app.py
+++ b/person_detection/app.py
@@ -12,7 +12,7 @@
 
 import config
 from person_detection import Camera
-import roc
+from roc import Roc
 
 
 app = flask.Flask(__name__)
@@ -20,7 +20,6 @@
 
 @app.route('/')
 def index():
-    global cameras
     """Video streaming home page."""
     log.info("{} - connected".format(flask.request.remote_addr))
     return flask.render_template('index.html', devices=config.cameras)
@@ -69,6 +68,12 @@
     args.add_argument("--key",
             help = "ROC api key",
             type = str)
+    args.add_argument("--user",
+            help = "ROC username",
+            type = str)
+    args.add_argument("--password",
+            help = "ROC password",
+            type = str)
     args.add_argument("--mbrlow",
             help = "Low range of MBR",
             default = 7000000,
@@ -86,9 +91,26 @@
 
 
 if __name__ == '__main__':
-    log.basicConfig(format="[ %(levelname)s ] %(message)s", level=log.DEBUG, stream=sys.stdout)
+    log.basicConfig(
+            format='%(asctime)s %(levelname)-8s %(message)s',
+            level=log.DEBUG,
+            datefmt='%Y-%m-%d %H:%M:%S',
+            stream=sys.stdout)
     log.debug("Starting person detection app")
+
     args = build_argparser().parse_args()
+
     if not args.noroc:
-        roc.set_mbr(args.key, args.devicegroup, args.mbrlow)
+        key = args.key
+        if key is None:
+            if args.user is not None and args.password is not None:
+                roc = Roc(args.user, args.password)
+                key = roc.get_key()
+            else:
+                log.error("Either key or user/password required")
+                sys.exit()
+
+        log.info("Device group:{} mbr:{}(low)".format(args.devicegroup, args.mbrlow))
+        roc.set_mbr(args.devicegroup, args.mbrlow)
+
     app.run(host='0.0.0.0', debug=True)
diff --git a/person_detection/base_camera.py b/person_detection/base_camera.py
index b8fa47c..e0018f5 100644
--- a/person_detection/base_camera.py
+++ b/person_detection/base_camera.py
@@ -6,7 +6,7 @@
 import logging as log
 from multiprocessing import Process, Queue, Value, Array, Lock
 
-import roc
+from roc import Roc
 import config
 
 
@@ -17,14 +17,14 @@
     cameras = Array('i', [0]*len(config.cameras))
     lock = Lock()
 
-    def __init__(self, device, key, mbrlow, mbrhigh, devicegroup, noroc):
+    def __init__(self, device, user, password, mbrlow, mbrhigh, devicegroup, noroc):
         self.mqttBroker = "localhost"
         self.device = device
-        self.key = key
         self.mbrlow = mbrlow
         self.mbrhigh = mbrhigh
         self.devicegroup = devicegroup
         self.noroc = noroc
+        self.roc = Roc(user, password)
 
         """Start the background camera process if it isn't running yet."""
         if BaseCamera.cameras[int(self.device)] == 0:
@@ -67,7 +67,7 @@
             BaseCamera.lock.release()
             self.set_resolution_high()
             if not self.noroc:
-                roc.set_mbr(self.key, self.devicegroup, self.mbrhigh)
+                self.roc.set_mbr(self.devicegroup, self.mbrhigh)
             self.detected = True
             self.start_timer()
 
@@ -80,7 +80,7 @@
             BaseCamera.activity_counter.value = 0
             self.set_resolution_low()
             if not self.noroc:
-                roc.set_mbr(self.key, self.devicegroup, self.mbrlow)
+                self.roc.set_mbr(self.devicegroup, self.mbrlow)
         BaseCamera.lock.release()
 
 
@@ -110,7 +110,7 @@
     def timer_expiry(self):
         now = time.time()
         diff = now - self.last_detected
-        log.info("timer_expiry() - now:{}, last_detected:{}".format(now, self.last_detected))
+        log.debug("timer_expiry() - now:{}, last_detected:{}".format(now, self.last_detected))
         if diff > 5.0:
             self.no_person_detected()
         else:
diff --git a/person_detection/person_detection.py b/person_detection/person_detection.py
index 86ebaa5..8d49589 100644
--- a/person_detection/person_detection.py
+++ b/person_detection/person_detection.py
@@ -27,7 +27,7 @@
         self.is_async_mode = True
         self.device = device
         self.client = client
-        super(Camera, self).__init__(device, args.key, args.mbrlow, args.mbrhigh, args.devicegroup, args.noroc)
+        super(Camera, self).__init__(device, args.user, args.password, args.mbrlow, args.mbrhigh, args.devicegroup, args.noroc)
 
     def __del__(self):
         # stream.release()
diff --git a/person_detection/roc.py b/person_detection/roc.py
index 7488af9..003d121 100644
--- a/person_detection/roc.py
+++ b/person_detection/roc.py
@@ -6,46 +6,77 @@
 import requests
 import json
 from requests.structures import CaseInsensitiveDict
+import logging as log
 
 
 URL = "https://roc.menlo.aetherproject.org/aether-roc-api/aether/v4.0.0/connectivity-service-v4/"
 #URL = "https://roc.staging.aether.onlab.us/aether-roc-api/aether/v4.0.0/connectivity-service-v4/"
 
 
-def headers(key):
-    h = CaseInsensitiveDict()
-    h["Content-Type"] = "application/json"
-    h["Authorization"] = "Bearer " + key
-    return h
+class Roc(object):
 
-def get_mbr(key, device_group):
-    url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
-    response = requests.get(url, headers=headers(key))
-    if response.status_code != 200:
-        print("Failed to get mbr, status_code: {}".format(response.status_code))
-        return None
-    mbr = json.loads(response.text)
-    return mbr
+    def __init__(self, user, password):
+        self.user = user
+        self.password = password
+        self.key = self.get_key()
 
-def set_mbr(key, device_group, mbr):
-    print("Set {} mbr to {}".format(device_group, mbr))
-    m = {'uplink' : mbr}
-    url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
-    response = requests.post(url, headers=headers(key), json=m)
-    assert response.status_code == 201, "Failed to set mbr"
-    if response.status_code != 201:
-        print("Failed to set mbr, device_group:{}, mbr:{}, status_code: {}".format(device_group, mbr, response.status_code))
+    def headers(self):
+        h = CaseInsensitiveDict()
+        h["Content-Type"] = "application/json"
+        h["Authorization"] = "Bearer " + self.key
+        return h
+
+    def get_mbr(self, device_group):
+        url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
+        response = requests.get(url, headers=self.headers())
+        if response.status_code != 200:
+            log.error("Failed to get mbr, status_code: {}".format(response.status_code))
+            return None
+        mbr = json.loads(response.text)
+        return mbr
+
+    def set_mbr(self, device_group, mbr):
+        log.info("Set {} mbr to {}".format(device_group, mbr))
+        m = {'uplink' : mbr}
+        url = URL + "vcs/vcs/vcs-{}/slice/mbr".format(device_group)
+        response = requests.post(url, headers=self.headers(), json=m)
+
+        # If error, renew api key and try again
+        if response.status_code != 201:
+            log.info("Renew ROC api key")
+            self.key = self.get_key()
+            response = requests.post(url, headers=self.headers(), json=m)
+            if response.status_code != 201:
+                log.error("Failed to set mbr, device_group:{}, mbr:{}, status_code: {}".format(device_group, mbr, response.status_code))
+                sys.exit()
+
+    def get_key(self):
+        url = "https://keycloak.opennetworking.org/auth/realms/master/protocol/openid-connect/token"
+        headers = CaseInsensitiveDict()
+        headers["Content-Type"] = "application/x-www-form-urlencoded"
+        data = {
+                'grant_type': 'password',
+                'client_id': 'aether-roc-gui',
+                'username': self.user,
+                'password': self.password,
+                'scope': 'openid profile email groups'
+                }
+        response = requests.post(url, data, headers)
+        key = json.loads(response.text)['access_token']
+        return key
 
 if __name__ == '__main__':
-    key = ""
-    cameras = "menlo-4g-cameras"
-    #cameras = "cameras-4g"
 
-    mbr = get_mbr(key, cameras)
+    # use valid keycloak user/password
+    roc = Roc("user", "password")
+
+    cameras = "menlo-4g-cameras"
+
+    mbr = roc.get_mbr(cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))
-    set_mbr(key, cameras, 5000000)
-    mbr = get_mbr(key, cameras)
+    roc.set_mbr(cameras, 5000000)
+    mbr = roc.get_mbr(cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))
-    set_mbr(key, cameras, 10000000)
-    mbr = get_mbr(key, cameras)
+    roc.set_mbr(cameras, 10000000)
+    mbr = roc.get_mbr(cameras)
     print("uplink mbr:{}, downlink mbr: {}".format(mbr["uplink"], mbr["downlink"]))