def conn(self): from zc.zk import ZooKeeper if connection: conn = connection[0] else: conn = ZooKeeper() connection.append(conn) return conn
def main(): logger.info("Enter") SLEEP_TIME = 300 parser = OptionParser() parser.add_option("-z", "--zkhosts", dest="zk_hosts", type='string', action='callback', callback=opt_callback, help="zookeeper list of host:port comma separated ") parser.add_option("-p", "--path", dest="zk_path", type='string', help="zookeeper root path") parser.add_option("-r", "--redishosts", dest="rs_hosts", type='string', action='callback', callback=opt_callback, help="redis list of host:port comma separated ") parser.add_option("-s", "--sleeptime", dest="sleep_time", type='int', help="waiting time in seconds between thread execution") options = parser.parse_args()[0] if options.sleep_time: SLEEP_TIME = options.sleep_time logger.info("SLEEP_TIME: %d", SLEEP_TIME) logger.info("Options: %r", options) logger.info("Acquiring a exclusive lock on ZooKeeper...") try: zk = ZooKeeper(','.join(options.zk_hosts)) with ZkLock(zk, ZOOKEEPER_LOCK): logger.info("Lock acquired! Connecting to Redis...") nm = RedisMonitor(zk, options.rs_hosts, SLEEP_TIME, options.zk_path) nm.execute() except FailedConnect, err: logger.critical(err)
def print_zk_snapshot(): # Dump all the ZooKeeper state at this point zk = ZooKeeper(ZK_CONNECT_STR) print zk.export_tree(ephemeral=True)
def lock_cli(): """Zktools Lock CLI""" from clint.textui import colored from clint.textui import columns from clint.textui import puts usage = "usage: %prog COMMAND" parser = OptionParser(usage=usage) parser.add_option("--host", dest="host", type="str", default='localhost:2181', help="Zookeeper host string") parser.add_option("--lock_root", dest="lock_root", type="str", default="/ZktoolsLocks", help="Lock root node") (options, args) = parser.parse_args() if len(args) < 1: puts(colored.red("Specify a command: list, remove, or show")) return command = args[0] if command not in ['list', 'remove', 'show']: puts(colored.red("Unrecognized command. Valid commands: list, remove, " "show")) return conn = ZooKeeper(options.host) if command == 'list': children = conn.get_children(options.lock_root) col1, col2 = 30, 70 puts(columns([colored.cyan("LOCK"), col1], [colored.cyan("STATUS"), col2])) for child in children: try: locks = conn.get_children(options.lock_root + '/' + child) except zookeeper.NoNodeException: continue if locks: status = colored.red("Locked") else: status = colored.green("Free") puts(columns([child, col1], [status, col2])) elif command == 'remove': if len(args) < 2: puts(colored.red("You must specify a node to remove.")) return conn.delete(options.lock_root + '/' + args[1]) elif command == 'show': if len(args) < 2: puts(colored.red("You must specify a node to show.")) return children = conn.get_children(options.lock_root + '/' + args[1]) col1, col2, col3 = 20, 15, None puts(columns([colored.cyan("LOCK HOLDER"), col1], [colored.cyan("DATA"), col2], [colored.cyan("INFO"), col3])) for child in sorted(children): try: node_name = '%s/%s/%s' % (options.lock_root, args[1], child) value, info = conn.get(node_name) except zookeeper.NoNodeException: continue info['created_ago'] = int(time.time() - (info['ctime'] / 1000)) info['modifed_ago'] = int(time.time() - (info['mtime'] / 1000)) puts(columns([child, col1], [value, col2], [str(info), col3]))
def __init__(self, zk_conn_str, zk_timeout=None): try: self._zk = ZooKeeper(zk_conn_str, zk_timeout) except FailedConnect as e: raise ZKConnectError(e)
class ZKUtil(object): # This is a free-for-all ACL that we should re-evaluate later ACL = [{"perms": 0x1f, "scheme": "world", "id": "anyone"}] """Abstracts all Kafka-specific ZooKeeper access.""" def __init__(self, zk_conn_str, zk_timeout=None): try: self._zk = ZooKeeper(zk_conn_str, zk_timeout) except FailedConnect as e: raise ZKConnectError(e) def close(self): self._zk.close() def broker_partitions_for(self, topic, force_partition_zero=False): """Return a list of BrokerPartitions based on values found in ZooKeeper. If you set force_partition_zero=True, we will always return partition 0 of a broker, even if no topic has been created for it yet. Consumers don't need this, because it means there's nothing there to read anyway. But Producers need to be bootstrapped with it. """ # Get the broker_ids first... if force_partition_zero: broker_ids = self.all_broker_ids() else: broker_ids = self.broker_ids_for(topic) # log.debug(u"broker_ids: {0}".format(broker_ids)) # Then the broker_strings for each broker broker_paths = map(self.path_for_broker, broker_ids) # log.debug(u"broker_paths: {0}".format(broker_paths)) broker_strings = map(self._zk_properties, broker_paths) # log.debug(u"broker_strings: {0}".format(broker_strings)) # Then the num_parts per broker (each could be set differently) broker_topic_paths = [self.path_for_broker_topic(broker_id, topic) for broker_id in broker_ids] # Every broker has at least one partition, even if it's not published num_parts = [] for p in broker_topic_paths: broker_parts = self._zk_properties(p) if self._zk.exists(p) else 1 num_parts.append(broker_parts) # log.debug(u"num_parts: {0}".format(num_parts)) # BrokerPartition return list( chain.from_iterable( BrokerPartition.from_zk(broker_id, broker_string, topic, n) for broker_id, broker_string, n in zip(broker_ids, broker_strings, num_parts) ) ) def offsets_state(self, consumer_group): """For a given consumer_group, get back a ZK state dict that looks like: { "topic1" : { "1-0" : 1002830, "1-1" : 1201221, "2-0" : 3232445, "2-1" : 2309495 } "topic2" : { "1-0" : 1002830, "1-1" : 1201221, "2-0" : 3232445, "2-1" : 2309495 } } Keys are topic names for that consumer group, and the values are the children in ZooKeeper -- other dicts with keys that are {broker_id}-{partition_id} to offsets. """ def topic_offsets(topic): broker_parts_path = self.path_for_offsets(consumer_group, topic) broker_parts = self._zk_children(broker_parts_path) return dict((bp, int(self._zk_properties(broker_parts_path + "/" + bp))) for bp in broker_parts) state = {} topics = self._zk_children("/consumers/{0}/offsets".format(consumer_group)) for topic in topics: state[topic] = topic_offsets(topic) return state def offsets_for(self, consumer_group, consumer_id, broker_partitions): """Return a dictionary mapping broker_partitions to offsets.""" UNKNOWN_OFFSET = 2**63 - 1 # Long.MAX_VALUE, it's what Kafka's client does bps_to_offsets = {} for bp in broker_partitions: # The topic might not exist at all, in which case no broker has # anything, so there's no point in making the offsets nodes and such if self._zk.exists(self.path_for_topic(bp.topic)): offset_path = self.path_for_offset(consumer_group, bp.topic, bp.broker_id, bp.partition) try: offset = int(self._zk_properties(offset_path)) except zookeeper.NoNodeException as ex: # This is counter to the Kafka client behavior, put here for # simplicity for now. FIXME: Dave self._create_path_if_needed(offset_path, 0) offset = 0 bps_to_offsets[bp] = offset return bps_to_offsets def save_offsets_for(self, consumer_group, bps_to_next_offsets): bp_ids_to_offsets = sorted((bp.id, offset) for bp, offset in bps_to_next_offsets.items()) log.debug("Saving offsets {0}".format(bp_ids_to_offsets)) for bp, next_offset in sorted(bps_to_next_offsets.items()): # The topic might not exist at all, in which case no broker has # anything, so there's no point in making the offsets nodes and such if self._zk.exists(self.path_for_topic(bp.topic)): offset_path = self.path_for_offset(consumer_group, bp.topic, bp.broker_id, bp.partition) try: offset_node = self._zk.properties(offset_path) except zookeeper.NoNodeException as ex: self._create_path_if_needed(offset_path, bp) offset_node = self._zk.properties(offset_path) next_offset = 0 # If we're creating the node now, assume we # need to start at 0. # None is the default value when we don't know what the next # offset is, possibly because the MessageSet is empty... if next_offset is not None: log.debug("Node %s: setting to %s" % (offset_node, next_offset)) offset_node.set(string_value=str(next_offset)) def broker_ids_for(self, topic): topic_path = self.path_for_topic(topic) try: topic_node_children = self._zk_children(topic_path) except zookeeper.NoNodeException: log.warn(u"Couldn't find {0} - No brokers have topic {1} yet?" .format(topic_path, topic)) return [] return sorted(int(broker_id) for broker_id in topic_node_children) def all_broker_ids(self): brokers_path = self.path_for_brokers() try: topic_node_children = self._zk_children(brokers_path) except zookeeper.NoNodeException: log.error(u"Couldn't find brokers entry {0}".format(brokers_path)) return [] return sorted(int(broker_id) for broker_id in topic_node_children) def consumer_ids_for(self, topic, consumer_group): """For a given consumer group, return a list of all consumer_ids that are currently registered in that group.""" # Gets the ids node below which are all consumer_ids in this group cg_path = self.path_for_consumer_ids(consumer_group) # All consumer_ids for this group, but not all of them are necessarily # interested in our topic consumer_ids_in_group = sorted(self._zk_children(cg_path)) consumer_id_paths = [self.path_for_consumer_id(consumer_group, consumer_id) for consumer_id in consumer_ids_in_group] consumer_id_data = [self._zk_properties(path) for path in consumer_id_paths] return [consumer_id for consumer_id, data in zip(consumer_ids_in_group, consumer_id_data) if topic in data] def register_consumer(self, consumer_group, consumer_id, topic): """Creates the following permanent node, if it does not exist already: /consumers/{consumer_group}/ids The data written at this node is just the consumer_id so that we can later track who created what. We then create the following emphemeral node: /consumers/{consumer_group}/ids/{consumer_id} The data written in this node is a dictionary of topic names (in unicode) to the number of threads that this consumer has registered for this topic (in our case, always one). """ self._create_path_if_needed(self.path_for_consumer_ids(consumer_group), consumer_id) # Create an emphermal node for this consumer consumer_id_path = self.path_for_consumer_id(consumer_group, consumer_id) log.info("Registering Consumer {0}, trying to create {1}" .format(consumer_id, consumer_id_path)) zookeeper.create(self._zk.handle, consumer_id_path, json.dumps({topic : 1}), # topic : # of threads ZKUtil.ACL, zookeeper.EPHEMERAL) def _create_path_if_needed(self, path, data=None): """Creates permanent nodes for all elements in the path if they don't already exist. Places data for each node created. (You'll probably want to use the consumer_id for this, just for accounting purposes -- it's not used as part of the balancing algorithm). Our zc.zk.ZooKeeper object doesn't know how to create nodes, so we have to dig into the zookeeper base library. Note that we can't create all of it in one go -- ZooKeeper only allows atomic operations, and so we're creating these one at a time. """ if not path.startswith("/"): raise ValueError("Paths must be fully qualified (begin with '/').") def _build_path(nodes): return "/" + "/".join(nodes) nodes_to_create = path[1:].split("/") # remove beginning "/" created_so_far = [] for node in nodes_to_create: created_path = _build_path(created_so_far) if node and node not in self._zk.children(created_path).data: node_to_create = _build_path(created_so_far + [node]) # If data is a string, we'll initialize the node with it... if isinstance(data, basestring): init_data = data else: init_data = json.dumps(data) zookeeper.create(self._zk.handle, node_to_create, init_data, ZKUtil.ACL) created_so_far.append(node) def path_for_broker_topic(self, broker_id, topic_name): return "{0}/{1}".format(self.path_for_topic(topic_name), broker_id) def path_for_brokers(self): return "/brokers/ids" def path_for_broker(self, broker_id): return "/brokers/ids/{0}".format(broker_id) def path_for_topics(self): return "/brokers/topics" def path_for_topic(self, topic): return "{0}/{1}".format(self.path_for_topics(), topic) def path_for_offsets(self, consumer_group, topic): return ("/consumers/{0}/offsets/{1}".format(consumer_group, topic)) def path_for_offset(self, consumer_group, topic, broker_id, partition): path_for_offsets = self.path_for_offsets(consumer_group, topic) return "{0}/{1}-{2}".format(path_for_offsets, broker_id, partition) def path_for_consumer_ids(self, consumer_group): return u"/consumers/{0}/ids".format(consumer_group) def path_for_consumer_id(self, consumer_group, consumer_id): return u"{0}/{1}".format(self.path_for_consumer_ids(consumer_group), consumer_id) def _zk_properties(self, path): node_data = self._zk.properties(path).data if 'string_value' in node_data: return node_data['string_value'] return node_data def _zk_children(self, path): return self._zk.children(path).data
# coding=utf-8 from kazoo.client import KazooClient from zc.zk import ZooKeeper import zc.zk import json # zk = ZooKeeper('zookeeper1.wohuafu.com:10013') # data =zk.export_tree('/') zk2 = ZooKeeper('zookeeper4.wohuafu.com:10155') # f = open('/Users/yupeng/Desktop/zknode','r') data = zk2.export_tree('/com') f = open("/Users/yupeng/Desktop/treeopmng",'w') f.write(data) # print data.decode('utf_8') # u = u'111' # print u # list2[i]=str() # for l in list2: # print l # print list2[l] # print zk.create_recursive(l,list2[l],None)
def __init__(self, zk_conn_str): try: self._zk = ZooKeeper(zk_conn_str) except FailedConnect as e: raise ZKConnectError(e)
class ZKUtil(object): # This is a free-for-all ACL that we should re-evaluate later ACL = [{"perms": 0x1f, "scheme": "world", "id": "anyone"}] """Abstracts all Kafka-specific ZooKeeper access.""" def __init__(self, zk_conn_str): try: self._zk = ZooKeeper(zk_conn_str) except FailedConnect as e: raise ZKConnectError(e) def close(self): self._zk.close() def broker_partitions_for(self, topic): """Return a list of BrokerPartitions based on values found in ZooKeeper.""" # Get the broker_ids first... broker_ids = self.broker_ids_for(topic) # log.debug(u"broker_ids: {0}".format(broker_ids)) # Then the broker_strings for each broker broker_paths = map(self.path_for_broker, broker_ids) # log.debug(u"broker_paths: {0}".format(broker_paths)) broker_strings = map(self._zk_properties, broker_paths) # log.debug(u"broker_strings: {0}".format(broker_strings)) # Then the num_parts per broker (each could be set differently) broker_topic_paths = [ self.path_for_broker_topic(broker_id, topic) for broker_id in broker_ids ] num_parts = map(self._zk_properties, broker_topic_paths) # log.debug(u"num_parts: {0}".format(num_parts)) # BrokerPartition return list( chain.from_iterable( BrokerPartition.from_zk(broker_id, broker_string, topic, n) for broker_id, broker_string, n in zip( broker_ids, broker_strings, num_parts))) def offsets_state(self, consumer_group): """For a given consumer_group, get back a ZK state dict that looks like: { "topic1" : { "1-0" : 1002830, "1-1" : 1201221, "2-0" : 3232445, "2-1" : 2309495 } "topic2" : { "1-0" : 1002830, "1-1" : 1201221, "2-0" : 3232445, "2-1" : 2309495 } } Keys are topic names for that consumer group, and the values are the children in ZooKeeper -- other dicts with keys that are {broker_id}-{partition_id} to offsets. """ def topic_offsets(topic): broker_parts_path = self.path_for_offsets(consumer_group, topic) broker_parts = self._zk_children(broker_parts_path) return dict( (bp, int(self._zk_properties(broker_parts_path + "/" + bp))) for bp in broker_parts) state = {} topics = self._zk_children( "/consumers/{0}/offsets".format(consumer_group)) for topic in topics: state[topic] = topic_offsets(topic) return state def offsets_for(self, consumer_group, consumer_id, broker_partitions): """Return a dictionary mapping broker_partitions to offsets.""" UNKNOWN_OFFSET = 2**63 - 1 # Long.MAX_VALUE, it's what Kafka's client does bps_to_offsets = {} for bp in broker_partitions: # The topic might not exist at all, in which case no broker has # anything, so there's no point in making the offsets nodes and such if self._zk.exists(self.path_for_topic(bp.topic)): offset_path = self.path_for_offset(consumer_group, bp.topic, bp.broker_id, bp.partition) try: offset = int(self._zk_properties(offset_path)) except zookeeper.NoNodeException as ex: # This is counter to the Kafka client behavior, put here for # simplicity for now. FIXME: Dave self._create_path_if_needed(offset_path, 0) offset = 0 bps_to_offsets[bp] = offset return bps_to_offsets def save_offsets_for(self, consumer_group, bps_to_next_offsets): bp_ids_to_offsets = sorted( (bp.id, offset) for bp, offset in bps_to_next_offsets.items()) log.debug("Saving offsets {0}".format(bp_ids_to_offsets)) for bp, next_offset in sorted(bps_to_next_offsets.items()): # The topic might not exist at all, in which case no broker has # anything, so there's no point in making the offsets nodes and such if self._zk.exists(self.path_for_topic(bp.topic)): offset_path = self.path_for_offset(consumer_group, bp.topic, bp.broker_id, bp.partition) try: offset_node = self._zk.properties(offset_path) except zookeeper.NoNodeException as ex: self._create_path_if_needed(offset_path, bps) offset_node = self._zk.properties(offset_path) next_offset = 0 # If we're creating the node now, assume we # need to start at 0. # None is the default value when we don't know what the next # offset is, possibly because the MessageSet is empty... if next_offset is not None: log.debug("Node %s: setting to %s" % (offset_node, next_offset)) offset_node.set(string_value=str(next_offset)) def broker_ids_for(self, topic): topic_path = self.path_for_topic(topic) try: topic_node_children = self._zk_children(topic_path) except zookeeper.NoNodeException: log.warn( u"Couldn't find {0} - No brokers have topic {1} yet?".format( topic_path, topic)) return [] return sorted(int(broker_id) for broker_id in topic_node_children) def consumer_ids_for(self, topic, consumer_group): """For a given consumer group, return a list of all consumer_ids that are currently registered in that group.""" # Gets the ids node below which are all consumer_ids in this group cg_path = self.path_for_consumer_ids(consumer_group) # All consumer_ids for this group, but not all of them are necessarily # interested in our topic consumer_ids_in_group = sorted(self._zk_children(cg_path)) consumer_id_paths = [ self.path_for_consumer_id(consumer_group, consumer_id) for consumer_id in consumer_ids_in_group ] consumer_id_data = [ self._zk_properties(path) for path in consumer_id_paths ] return [ consumer_id for consumer_id, data in zip( consumer_ids_in_group, consumer_id_data) if topic in data ] def register_consumer(self, consumer_group, consumer_id, topic): """Creates the following permanent node, if it does not exist already: /consumers/{consumer_group}/ids The data written at this node is just the consumer_id so that we can later track who created what. We then create the following emphemeral node: /consumers/{consumer_group}/ids/{consumer_id} The data written in this node is a dictionary of topic names (in unicode) to the number of threads that this consumer has registered for this topic (in our case, always one). """ self._create_path_if_needed(self.path_for_consumer_ids(consumer_group), consumer_id) # Create an emphermal node for this consumer consumer_id_path = self.path_for_consumer_id(consumer_group, consumer_id) log.info("Registering Consumer {0}, trying to create {1}".format( consumer_id, consumer_id_path)) zookeeper.create( self._zk.handle, consumer_id_path, json.dumps({topic: 1}), # topic : # of threads ZKUtil.ACL, zookeeper.EPHEMERAL) def _create_path_if_needed(self, path, data=None): """Creates permanent nodes for all elements in the path if they don't already exist. Places data for each node created. (You'll probably want to use the consumer_id for this, just for accounting purposes -- it's not used as part of the balancing algorithm). Our zc.zk.ZooKeeper object doesn't know how to create nodes, so we have to dig into the zookeeper base library. Note that we can't create all of it in one go -- ZooKeeper only allows atomic operations, and so we're creating these one at a time. """ if not path.startswith("/"): raise ValueError("Paths must be fully qualified (begin with '/').") def _build_path(nodes): return "/" + "/".join(nodes) nodes_to_create = path[1:].split("/") # remove beginning "/" created_so_far = [] for node in nodes_to_create: created_path = _build_path(created_so_far) if node and node not in self._zk.children(created_path).data: node_to_create = _build_path(created_so_far + [node]) # If data is a string, we'll initialize the node with it... if isinstance(data, basestring): init_data = data else: init_data = json.dumps(data) zookeeper.create(self._zk.handle, node_to_create, init_data, ZKUtil.ACL) created_so_far.append(node) def path_for_broker_topic(self, broker_id, topic_name): return "{0}/{1}".format(self.path_for_topic(topic_name), broker_id) def path_for_brokers(self): return "/brokers/ids" def path_for_broker(self, broker_id): return "/brokers/ids/{0}".format(broker_id) def path_for_topics(self): return "/brokers/topics" def path_for_topic(self, topic): return "{0}/{1}".format(self.path_for_topics(), topic) def path_for_offsets(self, consumer_group, topic): return ("/consumers/{0}/offsets/{1}".format(consumer_group, topic)) def path_for_offset(self, consumer_group, topic, broker_id, partition): path_for_offsets = self.path_for_offsets(consumer_group, topic) return "{0}/{1}-{2}".format(path_for_offsets, broker_id, partition) def path_for_consumer_ids(self, consumer_group): return u"/consumers/{0}/ids".format(consumer_group) def path_for_consumer_id(self, consumer_group, consumer_id): return u"{0}/{1}".format(self.path_for_consumer_ids(consumer_group), consumer_id) def _zk_properties(self, path): node_data = self._zk.properties(path).data if 'string_value' in node_data: return node_data['string_value'] return node_data def _zk_children(self, path): return self._zk.children(path).data
def import_node(host, data): zk = ZooKeeper(host) zk.import_tree(data)
def export_node(host, path='/com'): zk = ZooKeeper(host) data = zk.export_tree(path) return data
def lock_cli(): """Zktools Lock CLI""" from clint.textui import colored from clint.textui import columns from clint.textui import puts usage = "usage: %prog COMMAND" parser = OptionParser(usage=usage) parser.add_option("--host", dest="host", type="str", default='localhost:2181', help="Zookeeper host string") parser.add_option("--lock_root", dest="lock_root", type="str", default="/ZktoolsLocks", help="Lock root node") (options, args) = parser.parse_args() if len(args) < 1: puts(colored.red("Specify a command: list, remove, or show")) return command = args[0] if command not in ['list', 'remove', 'show']: puts( colored.red("Unrecognized command. Valid commands: list, remove, " "show")) return conn = ZooKeeper(options.host) if command == 'list': children = conn.get_children(options.lock_root) col1, col2 = 30, 70 puts( columns([colored.cyan("LOCK"), col1], [colored.cyan("STATUS"), col2])) for child in children: try: locks = conn.get_children(options.lock_root + '/' + child) except zookeeper.NoNodeException: continue if locks: status = colored.red("Locked") else: status = colored.green("Free") puts(columns([child, col1], [status, col2])) elif command == 'remove': if len(args) < 2: puts(colored.red("You must specify a node to remove.")) return conn.delete(options.lock_root + '/' + args[1]) elif command == 'show': if len(args) < 2: puts(colored.red("You must specify a node to show.")) return children = conn.get_children(options.lock_root + '/' + args[1]) col1, col2, col3 = 20, 15, None puts( columns([colored.cyan("LOCK HOLDER"), col1], [colored.cyan("DATA"), col2], [colored.cyan("INFO"), col3])) for child in sorted(children): try: node_name = '%s/%s/%s' % (options.lock_root, args[1], child) value, info = conn.get(node_name) except zookeeper.NoNodeException: continue info['created_ago'] = int(time.time() - (info['ctime'] / 1000)) info['modifed_ago'] = int(time.time() - (info['mtime'] / 1000)) puts(columns([child, col1], [value, col2], [str(info), col3]))