7 This tool provides real-time visualization of the cluster member roles for all
8 shards in the config datastore.
10 A file named 'cluster.json' contaning a list of the IP addresses of the
11 controllers is required. This resides in the same directory as monitor.py.
12 "user" and "pass" are not required for monitor.py, but they may be
13 needed for other apps in this folder. The file should look like this:
27 Usage:python monitor.py
29 from io import BytesIO
39 def rest_get(restURL):
40 rest_buffer = BytesIO()
42 c.setopt(c.TIMEOUT, 2)
43 c.setopt(c.CONNECTTIMEOUT, 1)
44 c.setopt(c.FAILONERROR, False)
45 c.setopt(c.URL, str(restURL))
46 c.setopt(c.HTTPGET, 0)
47 c.setopt(c.WRITEFUNCTION, rest_buffer.write)
50 return json.loads(rest_buffer.getvalue())
53 def getClusterRolesWithCurl(shardName, *args):
57 for i, ip in enumerate(ips):
58 controller_state[ip] = None
59 url = 'http://' + ip + ':' + '8181/jolokia/read/org.opendaylight.controller:'
60 url += 'Category=Shards,name=' + names[i]
61 url += '-shard-' + shardName + '-config,type=DistributedConfigDatastore'
64 if resp['status'] != 200:
65 controller_state[ip] = 'HTTP ' + str(resp['status'])
67 data_value = resp['value']
68 controller_state[ip] = data_value['RaftState']
70 if 'timed out' in str(sys.exc_info()[1]):
71 controller_state[ip] = 'timeout'
72 elif 'JSON' in str(sys.exc_info()):
73 controller_state[ip] = 'JSON error'
74 elif 'connect to host' in str(sys.exc_info()):
75 controller_state[ip] = 'no connection'
77 controller_state[ip] = 'down'
78 return controller_state
81 def size_and_color(cluster_roles, field_length, ip_addr):
83 status_dict['txt'] = string.center(str(cluster_roles[ip_addr]), field_length)
84 if cluster_roles[ip_addr] == "Leader":
85 status_dict['color'] = curses.color_pair(2)
86 elif cluster_roles[ip_addr] == "Follower":
87 status_dict['color'] = curses.color_pair(3)
88 elif cluster_roles[ip_addr] == "Candidate":
89 status_dict['color'] = curses.color_pair(5)
91 status_dict['color'] = curses.color_pair(0)
97 with open('cluster.json') as cluster_file:
98 data = json.load(cluster_file)
100 print str(sys.exc_info())
101 print 'Unable to open the file cluster.json'
104 controllers = data["cluster"]["controllers"]
106 print str(sys.exc_info())
107 print 'Error reading the file cluster.json'
110 controller_names = []
112 # Retrieve controller names and shard names.
113 for controller in controllers:
114 url = "http://" + controller + ":8181/jolokia/read/org.opendaylight.controller:"
115 url += "Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore"
119 print 'Unable to retrieve shard names from ' + controller
120 print 'Are all controllers up?'
121 print str(sys.exc_info()[1])
123 print 'shards from the first controller'
125 # grab the controller name from the first shard
126 name = data['value']['LocalShards'][0]
128 pos = name.find('-shard-')
131 controller_names.append(name[:name.find('-shard-')])
133 # collect shards found in any controller; does not require all controllers to have the same shards
134 for localShard in data['value']['LocalShards']:
135 shardName = localShard[(localShard.find("-shard-")+7):localShard.find("-config")]
136 Shards.add(shardName)
137 print controller_names
140 stdscr = curses.initscr()
148 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
149 curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_GREEN)
150 curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_BLUE)
151 curses.init_pair(4, curses.COLOR_WHITE, curses.COLOR_YELLOW)
152 curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_YELLOW)
154 # display controller and shard headers
155 for data_column, controller in enumerate(controller_names):
156 stdscr.addstr(0, field_len * (data_column + 1), string.center(controller, field_len), curses.color_pair(1))
157 for row, shard in enumerate(Shards):
158 stdscr.addstr(row + 1, 0, shard, curses.color_pair(1))
159 stdscr.addstr(len(Shards) + 2, 0, 'Press q to quit.', curses.color_pair(1))
162 # display shard status
165 while key != ord('q') and key != ord('Q'):
169 for row, shard_name in enumerate(Shards):
170 cluster_stat = getClusterRolesWithCurl(shard_name, controllers, controller_names)
171 for data_column, controller in enumerate(controllers):
172 status = size_and_color(cluster_stat, field_len, controller)
173 stdscr.addstr(row + 1, field_len * (data_column + 1), status['txt'], status['color'])
175 if odd_or_even % 2 == 0:
176 stdscr.addstr(0, field_len/2 - 2, " <3 ", curses.color_pair(5))
178 stdscr.addstr(0, field_len/2 - 2, " <3 ", curses.color_pair(0))