fixing pep8 problems for test verify tox job
[integration/test.git] / tools / clustering / cluster-monitor / monitor.py
index 26a9d7a80678acd82a0a7f337bd02ed232d99d8f..d6ef370031badc8f4eb1361bed5c0d29103a37c6 100644 (file)
@@ -2,29 +2,30 @@
 """
 Cluster Monitor Tool
 Author: Phillip Shea
-Updated: 2015-May-07
+Updated: 2016-Mar-07
 
 This tool provides real-time visualization of the cluster member roles for all
-shards in the config datastore.
+shards in either the config or operational datastore.
 
-A file named 'cluster.json' contaning a list of the IP addresses of the
-controllers is required. This resides in the same directory as monitor.py.
+A file named 'cluster.json' contaning a list of the IP addresses and port numbers
+of the controllers is required. This resides in the same directory as monitor.py.
 "user" and "pass" are not required for monitor.py, but they may be
 needed for other apps in this folder. The file should look like this:
 
     {
         "cluster": {
             "controllers": [
-                "172.17.10.93",
-                "172.17.10.94",
-                "172.17.10.95"
+                {"ip": "172.17.10.93", "port": "8181"},
+                {"ip": "172.17.10.93", "port": "8181"},
+                {"ip": "172.17.10.93", "port": "8181"}
             ],
             "user": "username",
-            "pass": "password"
+            "pass": "password",
+            "shards_to_exclude": []  # list of shard names to omit from output
         }
     }
 
-Usage:python monitor.py
+Usage:python monitor.py [-d data_store_name]
 """
 from io import BytesIO
 import time
@@ -34,9 +35,10 @@ import sys
 import json
 import pycurl
 import string
+import argparse
 
 
-def rest_get(restURL):
+def rest_get(restURL, username, password):
     rest_buffer = BytesIO()
     c = pycurl.Curl()
     c.setopt(c.TIMEOUT, 2)
@@ -45,36 +47,37 @@ def rest_get(restURL):
     c.setopt(c.URL, str(restURL))
     c.setopt(c.HTTPGET, 0)
     c.setopt(c.WRITEFUNCTION, rest_buffer.write)
+    c.setopt(pycurl.USERPWD, "%s:%s" % (str(username), str(password)))
     c.perform()
     c.close()
     return json.loads(rest_buffer.getvalue())
 
 
 def getClusterRolesWithCurl(shardName, *args):
-    ips = args[0]
+    controllers = args[0]
     names = args[1]
     controller_state = {}
-    for i, ip in enumerate(ips):
-        controller_state[ip] = None
-        url = 'http://' + ip + ':' + '8181/jolokia/read/org.opendaylight.controller:'
+    for i, controller in enumerate(controllers):
+        controller_state[controller["ip"]] = None
+        url = "http://" + controller["ip"] + ":" + controller["port"] + "/jolokia/read/org.opendaylight.controller:"
         url += 'Category=Shards,name=' + names[i]
-        url += '-shard-' + shardName + '-config,type=DistributedConfigDatastore'
+        url += '-shard-' + shardName + '-' + data_store.lower() + ',type=Distributed' + data_store + 'Datastore'
         try:
-            resp = rest_get(url)
+            resp = rest_get(url, username, password)
             if resp['status'] != 200:
-                controller_state[ip] = 'HTTP ' + str(resp['status'])
+                controller_state[controller["ip"]] = 'HTTP ' + str(resp['status'])
             if 'value' in resp:
                 data_value = resp['value']
-                controller_state[ip] = data_value['RaftState']
+                controller_state[controller["ip"]] = data_value['RaftState']
         except:
             if 'timed out' in str(sys.exc_info()[1]):
-                controller_state[ip] = 'timeout'
+                controller_state[controller["ip"]] = 'timeout'
             elif 'JSON' in str(sys.exc_info()):
-                controller_state[ip] = 'JSON error'
+                controller_state[controller["ip"]] = 'JSON error'
             elif 'connect to host' in str(sys.exc_info()):
-                controller_state[ip] = 'no connection'
+                controller_state[controller["ip"]] = 'no connection'
             else:
-                controller_state[ip] = 'down'
+                controller_state[controller["ip"]] = 'down'
     return controller_state
 
 
@@ -92,6 +95,15 @@ def size_and_color(cluster_roles, field_length, ip_addr):
     return status_dict
 
 
+parser = argparse.ArgumentParser()
+parser.add_argument('-d', '--datastore', default='Config', type=str,
+                    help='polling can be done on "Config" or "Operational" data stores')
+args = parser.parse_args()
+data_store = args.datastore
+if data_store != 'Config' and data_store != 'Operational':
+    print 'Only "Config" or "Operational" data store is available for polling'
+    exit(1)
+
 try:
     with open('cluster.json') as cluster_file:
         data = json.load(cluster_file)
@@ -101,6 +113,9 @@ except:
     exit(1)
 try:
     controllers = data["cluster"]["controllers"]
+    shards_to_exclude = data["cluster"]["shards_to_exclude"]
+    username = data["cluster"]["user"]
+    password = data["cluster"]["pass"]
 except:
     print str(sys.exc_info())
     print 'Error reading the file cluster.json'
@@ -110,12 +125,14 @@ controller_names = []
 Shards = set()
 # Retrieve controller names and shard names.
 for controller in controllers:
-    url = "http://" + controller + ":8181/jolokia/read/org.opendaylight.controller:"
-    url += "Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore"
+    url = "http://" + controller["ip"] + ":" + controller["port"] + "/jolokia/read/org.opendaylight.controller:"
+    url += "Category=ShardManager,name=shard-manager-" + data_store.lower()\
+           + ",type=Distributed" + data_store + "Datastore"
+    rest_get(url, username, password)
     try:
-        data = rest_get(url)
+        data = rest_get(url, username, password)
     except:
-        print 'Unable to retrieve shard names from ' + controller
+        print 'Unable to retrieve shard names from ' + str(controller)
         print 'Are all controllers up?'
         print str(sys.exc_info()[1])
         exit(1)
@@ -131,11 +148,12 @@ for controller in controllers:
 
     # collect shards found in any controller; does not require all controllers to have the same shards
     for localShard in data['value']['LocalShards']:
-        shardName = localShard[(localShard.find("-shard-")+7):localShard.find("-config")]
-        Shards.add(shardName)
+        shardName = localShard[(localShard.find("-shard-") + 7):localShard.find("-" + data_store.lower())]
+        if shardName not in shards_to_exclude:
+            Shards.add(shardName)
 print controller_names
 print Shards
-field_len = max(map(len, Shards))+2
+field_len = max(map(len, Shards)) + 2
 
 stdscr = curses.initscr()
 curses.noecho()
@@ -155,7 +173,7 @@ curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_YELLOW)
 for row, controller in enumerate(controller_names):
     stdscr.addstr(row + 1, 0, string.center(controller, field_len), curses.color_pair(1))
 for data_column, shard in enumerate(Shards):
-    stdscr.addstr(0, (field_len+1) * (data_column + 1), string.center(shard, field_len), curses.color_pair(1))
+    stdscr.addstr(0, (field_len + 1) * (data_column + 1), string.center(shard, field_len), curses.color_pair(1))
 stdscr.addstr(len(Shards) + 2, 0, 'Press q to quit.', curses.color_pair(1))
 stdscr.refresh()
 
@@ -167,16 +185,17 @@ while key != ord('q') and key != ord('Q'):
     key = stdscr.getch()
 
     for data_column, shard_name in enumerate(Shards):
-        cluster_stat = getClusterRolesWithCurl(shard_name, controllers, controller_names)
-        for row, controller in enumerate(controllers):
-            status = size_and_color(cluster_stat, field_len, controller)
-            stdscr.addstr(row + 1, (field_len+1) * (data_column + 1), status['txt'], status['color'])
-    time.sleep(0.5)
-    if odd_or_even % 2 == 0:
-        stdscr.addstr(0, field_len/2 - 2, " <3 ", curses.color_pair(5))
-    else:
-        stdscr.addstr(0, field_len/2 - 2, " <3 ", curses.color_pair(0))
-    stdscr.refresh()
+        if shard_name not in shards_to_exclude:
+            cluster_stat = getClusterRolesWithCurl(shard_name, controllers, controller_names)
+            for row, controller in enumerate(controllers):
+                status = size_and_color(cluster_stat, field_len, controller["ip"])
+                stdscr.addstr(row + 1, (field_len + 1) * (data_column + 1), status['txt'], status['color'])
+        time.sleep(0.5)
+        if odd_or_even % 2 == 0:
+            stdscr.addstr(0, field_len / 2 - 2, " <3 ", curses.color_pair(5))
+        else:
+            stdscr.addstr(0, field_len / 2 - 2, " <3 ", curses.color_pair(0))
+        stdscr.refresh()
 
 # clean up
 curses.nocbreak()