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)
96 with open('cluster.json') as cluster_file:
97 data = json.load(cluster_file)
99 print str(sys.exc_info())
100 print 'Unable to open the file cluster.json'
103 controllers = data["cluster"]["controllers"]
105 print str(sys.exc_info())
106 print 'Error reading the file cluster.json'
109 controller_names = []
111 # Retrieve controller names and shard names.
112 for controller in controllers:
113 url = "http://" + controller + ":8181/jolokia/read/org.opendaylight.controller:"
114 url += "Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore"
118 print 'Unable to retrieve shard names from ' + controller
119 print 'Are all controllers up?'
120 print str(sys.exc_info()[1])
122 print 'shards from the first controller'
124 # grab the controller name from the first shard
125 name = data['value']['LocalShards'][0]
127 pos = name.find('-shard-')
130 controller_names.append(name[:name.find('-shard-')])
132 # collect shards found in any controller; does not require all controllers to have the same shards
133 for localShard in data['value']['LocalShards']:
134 shardName = localShard[(localShard.find("-shard-") + 7):localShard.find("-config")]
135 Shards.add(shardName)
136 print controller_names
138 field_len = max(map(len, Shards)) + 2
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 row, controller in enumerate(controller_names):
156 stdscr.addstr(row + 1, 0, string.center(controller, field_len), curses.color_pair(1))
157 for data_column, shard in enumerate(Shards):
158 stdscr.addstr(0, (field_len + 1) * (data_column + 1), string.center(shard, field_len), 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 data_column, shard_name in enumerate(Shards):
170 cluster_stat = getClusterRolesWithCurl(shard_name, controllers, controller_names)
171 for row, controller in enumerate(controllers):
172 status = size_and_color(cluster_stat, field_len, controller)
173 stdscr.addstr(row + 1, (field_len + 1) * (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))