#!/usr/bin/env python
import time
import os
import threading
import optparse
import datetime
import sys
import select
import signal
from kazoo.client import KazooClient
debug = False
def _dump_stat( stat ):
if stat is None:
print("\tStat is None")
else:
createTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(stat.ctime / 1000.0))
modTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(stat.mtime / 1000.0))
print("\tStat is:")
print("\t\tacl_version: %d" % stat.aversion )
print("\t\tversion: %s" % stat.version )
print("\t\tcreated: %s" % createTime )
print("\t\tcreation_transaction_id: %d" % stat.czxid )
print("\t\tlast_modified: %s" % modTime )
print("\t\tlast_modified_transaction_id: %d" % stat.mzxid)
print("\t\tdata_length: %d" % stat.dataLength )
print("\t\tchildren_count: %d" % stat.numChildren )
def _dump_event( event ):
if event is None:
print("\tEvent is None")
else:
print( event )
print('Event Type %s' % event.type )
print('Event State %s' % event.state )
if event.path is None:
print("\tNode Path is None")
else:
print("\tNode Path is: %s" % event.path)
def dump_child_event( parent_node, children, event ):
global debug
if debug == False:
return;
print("CHILDREN EVENT OCCURS: parent is %s." % parent_node )
if event is None:
print("\tEvent is None")
else:
_dump_event( event )
if children is not None:
i = 0;
for child in children:
i += 1
print( "\tChild node %d is %s" % (i, child) )
def dump_node_event( node, data, stat, event ):
global debug
if debug == False:
return;
print("NODE EVENT OCCURS: node is %s." % node )
_dump_event( event )
_dump_stat( stat )
print("\tNodeData is: \"%s\"" % data )
parser = optparse.OptionParser( description='Snoop on Zookeeper events for a DCS cluster.' )
parser.add_option( '--debug', dest='debugOn', action='store_true', default=False,
help='print out verbose debugging information' )
parser.add_option( '--zkport', dest='zkport', default="localhost:2181",
help='CSV string containing ZK host:port pairs' )
default_user = os.path.basename(os.environ['HOME'])
parser.add_option( '--cluster', dest='cluster', default=default_user + "_cluster",
help='cluster id of the cluster to monitor' )
opts, args = parser.parse_args()
if opts.zkport and opts.cluster:
cluster = opts.cluster
zkportpairs = opts.zkport
else:
print("Must either specify a config file or both zkport and cluster")
print( parser.print_help() )
sys.exit(0)
memberNode = '/perforce/cluster/' + cluster + '/members'
clusterRootNode = '/perforce/cluster/' + cluster
electionNode = clusterRootNode + '/election'
workspaceNode = clusterRootNode + '/workspace'
masterNode = clusterRootNode + '/master'
routerNode = clusterRootNode + '/router'
# Global Locked Access Variables
list_lock = threading.RLock()
member_children = []
member_set = set(member_children)
election_children = []
election_set = set(election_children)
router_children = []
router_set = set(router_children)
workspace_children = []
workspace_set = set(workspace_children)
masterData = ''
zk = KazooClient(hosts=zkportpairs, read_only=True )
zk.start()
zk.ensure_path(electionNode)
zk.ensure_path(workspaceNode)
zk.ensure_path(routerNode)
zk.ensure_path(memberNode)
# connection watch
def my_listener(state):
if state == KazooState.LOST:
print("ERROR - SESSION WAS LOST!!!")
elif state == KazooState.SUSPENDED:
print("ERROR - DISCONNECTED!!!")
else:
print("ERROR - DIS & RE-CONNECTED!!!")
zk.add_listener( my_listener )
# utility routine
def show_status():
print("CURRENT ZOOKEEPER STATUS")
print("----------------------------------------------------------------------------------")
if zk.exists( masterNode ):
(data, stat) = zk.get( masterNode )
print("MASTER is UP: %s" % data)
else:
print("MASTER is DOWN")
print("ELECTION NODES")
children = zk.get_children(electionNode)
for child in children:
childNode = electionNode + '/' + child
(data, stat) = zk.get(childNode)
print("\tNode %s has data: %s" % (child, data))
print("WORKSPACE NODES")
children = zk.get_children(workspaceNode)
for child in children:
childNode = workspaceNode + '/' + child
(data, stat) = zk.get(childNode)
print("\tNode %s has data: %s" % (child, data))
print("ROUTER NODES")
children = zk.get_children(routerNode)
for child in children:
childNode = routerNode + '/' + child
(data, stat) = zk.get(childNode)
print("\tNode %s has data: %s" % (child, data))
print("MEMBER NODES")
children = zk.get_children(memberNode)
for child in children:
childNode = memberNode + '/' + child
(data, stat) = zk.get(childNode)
print("\tNode %s has data: %s" % (child, data))
print("----------------------------------------------------------------------------------")
print("")
# data watches
def election_data_changed(data, stat, event):
dump_node_event( 'Election node', data, stat, event )
with list_lock:
if event is None:
if data:
print("+++++++++++++++ Child of %s data is now at version: %s, data: %s" %
(electionNode, stat.version, data.decode("utf-8")))
else:
print("+++++++++++++++ %s/%s Event type: %s (state %)" %
(electionNode, event.path, event.type, event.state))
if data is not None and data:
print("+++++++++++++++ %s/%s data is now at version: %s, data: %s" %
( electionNode, event.path, stat.version, data.decode("utf-8")))
def wksp_data_changed(data, stat, event):
dump_node_event( 'Workspace node', data, stat, event )
with list_lock:
if event is None:
if data:
print("+++++++++++++++ Child of %s data is now at version: %s, data: %s" %
(workspaceNode, stat.version, data.decode("utf-8")))
else:
print("+++++++++++++++ %s/%s Event type: %s (state %)" %
(workspaceNode, event.path, event.type, event.state))
if data is not None and data:
print("+++++++++++++++ %s/%s data is now at version: %s, data: %s" %
( workspaceNode, event.path, stat.version, data.decode("utf-8")))
def router_data_changed(data, stat, event):
dump_node_event( 'Router node', data, stat, event )
with list_lock:
if event is None:
if data:
print("+++++++++++++++ Child of %s data is now at version: %s, data: %s" %
(routerNode, stat.version, data.decode("utf-8")))
else:
print("+++++++++++++++ %s/%s Event type: %s (state %)" %
(routerNode, event.path, event.type, event.state))
if data is not None and data:
print("+++++++++++++++ %s/%s data is now at version: %s, data: %s" %
( routerNode, event.path, stat.version, data.decode("utf-8")))
def member_data_changed(data, stat, event):
dump_node_event( 'Member node', data, stat, event )
with list_lock:
if event is None:
if data:
print("+++++++++++++++ Child of %s data is now at version: %s, data: %s" %
(memberNode, stat.version, data.decode("utf-8")))
else:
print("+++++++++++++++ %s/%s Event type: %s (state %)" %
(memberNode, event.path, event.type, event.state))
if data is not None and data:
print("+++++++++++++++ %s/%s data is now at version: %s, data: %s" %
( memberNode, event.path, stat.version, data.decode("utf-8")))
# setup watches on master node
def print_master_status( masterExists ):
if masterExists:
@zk.DataWatch( masterNode )
def master_data_changed(data, stat):
with list_lock:
if data:
print("+++++++++++++++ %s data is now at version: %s, data: %s" %
(masterNode, stat.version, data.decode("utf-8")))
else:
print("!!!!!!! MASTER DOES NOT EXIST")
def master_changed( event ):
print("MASTER NODE STATUS")
if event is not None:
if(debug == False):
print("-------- %s Event type: %s (state: %s)"
% (masterNode, event.type, event.state))
else:
print("-------- %s Event type: Zookeeper Monitor Startup" % masterNode )
masterExists = zk.exists( masterNode, watch=master_changed )
print_master_status( masterExists )
masterExists = zk.exists( masterNode, watch=master_changed )
print("MASTER NODE STATUS")
print("-------- %s Event type: Zookeeper Monitor Startup" % masterNode )
print_master_status( masterExists )
@zk.ChildrenWatch(electionNode, send_event=True)
def elect_child_changed(children, event):
global election_children
print(' ')
print("ELECTION CHILDREN are now: %s" % children)
with list_lock:
dump_child_event( 'election children', children, event )
if event is not None:
if(debug == False):
print("-------- %s Event type: %s (state %)"
% (event.path, event.type, event.state))
children_set = set(children)
for child in children:
if child not in election_set:
childNode = electionNode + '/' + child
election_children.append(child)
print("-------- Election Node %s Created" % childNode )
zk.DataWatch( childNode, func=election_data_changed, send_event=True )
for child in election_children:
if child not in children_set:
childNode = electionNode + '/' + child
election_children.remove(child)
print("-------- Election Node %s Deleted" % childNode )
return True
@zk.ChildrenWatch(workspaceNode, send_event=True)
def wksp_child_changed(children, event):
global workspace_children
print(' ')
print("WORKSPACE CHILDREN are now: %s" % children)
with list_lock:
dump_child_event( 'workspace children', children, event )
if event is not None:
if(debug == False):
print("-------- %s Event type: %s (state %)"
% (event.path, event.type, event.state))
children_set = set(children)
for child in children:
if child not in workspace_set:
childNode = workspaceNode + '/' + child
workspace_children.append(child)
print("-------- Workspace Node %s Created" % childNode )
zk.DataWatch( childNode, func=wksp_data_changed, send_event=True )
for child in workspace_children:
if child not in children_set:
childNode = workspaceNode + '/' + child
workspace_children.remove(child)
print("-------- Workspace Node %s Deleted" % childNode )
return True
@zk.ChildrenWatch(routerNode, send_event=True)
def router_child_changed(children, event):
global router_children
print(' ')
print("ROUTER CHILDREN are now: %s" % children)
with list_lock:
dump_child_event( 'router children', children, event )
if event is not None:
if(debug == False):
print("-------- %s Event type: %s (state %)"
% (event.path, event.type, event.state))
children_set = set(children)
for child in children:
if child not in router_set:
childNode = routerNode + '/' + child
router_children.append(child)
print("-------- Router Node %s Created" % childNode )
zk.DataWatch( childNode, func=router_data_changed, send_event=True )
for child in router_children:
if child not in children_set:
childNode = routerNode + '/' + child
router_children.remove(child)
print("-------- Router Node %s Deleted" % childNode )
return True
@zk.ChildrenWatch(memberNode, send_event=True)
def member_child_changed(children, event):
global member_children
print(' ')
print("MEMBER CHILDREN are now: %s" % children)
with list_lock:
dump_child_event( 'member children', children, event )
if event is not None:
if(debug == False):
print("-------- %s Event type: %s (state %)"
% (event.path, event.type, event.state))
children_set = set(children)
for child in children:
if child not in member_set:
childNode = memberNode + '/' + child
member_children.append(child)
print("-------- member Node %s Created" % childNode )
zk.DataWatch( childNode, func=member_data_changed, send_event=True )
for child in member_children:
if child not in children_set:
childNode = memberNode + '/' + child
member_children.remove(child)
print("-------- member Node %s Deleted" % childNode )
return True
def handler(signum, frame):
print ('Stopping zkMonitor with signal %d' % signum)
zk.stop()
sys.exit(0)
# Set the signal handlers
signal.signal(signal.SIGHUP, handler)
signal.signal(signal.SIGINT, handler)
while True:
sys.stdin in select.select([sys.stdin], [], [])[0]
input = sys.stdin.readline()
print("What do you want to do: quit [q], show status[s], nothing[n] or any other input.")
input = raw_input('Your choice [q,s,N]: ').strip().lower()
if input == 'q':
zk.stop()
sys.exit(0)
elif input == 's':
show_status()