{
"info": {
"author": "Jim Fulton",
"author_email": "jim@zope.com",
"bugtrack_url": null,
"classifiers": [],
"description": "=============\nZEO ZooKeeper\n=============\n\nManaging addresses, and especially ports is a drag. ZooKeeper can be\nused as a service registry. Servers can register themselves and\nclients can find services there. The ``zc.zkzeo`` package provides\nsupport for registering ZEO servers and a ZEO client storage that gets\naddresses from ZooKeeper.\n\n.. contents::\n\nRunning ZEO servers\n===================\n\nTo run a ZEO server, and register it with ZooKeeper, first create a\nZEO configuration file::\n\n \n address 127.0.0.1\n \n\n \n connection zookeeper.example.com:2181\n path /databases/demo\n \n\n \n path demo.fs\n \n\n.. -> server_conf\n\nThe ZEO configuration file has the same options as usual, plus a\n``zookeeper`` section with two options:\n\n``connection``\n A ZooKeeper connection string. This is typically a list of\n *HOST:PORT* pairs separated by commas.\n\n``path``\n The path at which to register the server. The path must already\n exist. When the server starts, it will register itself by creating\n a subnode of the path with a name consisting of it's address.\n\n(You can also specify a ZooKeeper session timeout, in milliseconds,\nwith a ``session-timeout`` option.)\n\nWhen specifying the ZEO address, you can leave off the port and the\noperating system will assign it for you.\n\nTo start the server, use the ``zkrunzeo`` script::\n\n $ bin/zkrunzeo -C FILENAME\n\n.. test\n\n >>> import zc.zkzeo.runzeo, zc.zk\n >>> stop = zc.zkzeo.runzeo.test(\n ... server_conf)\n >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')\n >>> zk.print_tree('/databases/demo')\n /demo\n /127.0.0.1:56824\n pid = 88841\n\n >>> stop().exception\n >>> zk.print_tree('/databases/demo')\n /demo\n\nwhere ``FILENAME`` is the name of the configuration file you created.\n\nIncluding a ``zc.monitor`` monitoring server\n--------------------------------------------\n\nThe `zc.monitor `_ package\nprovides a simple extensible command server for gathering monitoring\ndata or providing run-time control of servers. If ``zc.monitor`` is\nin the Python path, ``zc.zkzeo`` can start a monitor server and make it's\naddress available as the ``monitor`` property of of a server's\nephemeral port. To request this, we use a ``monitor-server`` option in\nthe ``zookeeper`` section::\n\n \n address 127.0.0.1\n \n\n \n connection zookeeper.example.com:2181\n path /databases/demo\n monitor-server 127.0.0.1\n \n\n \n path demo.fs\n \n\n.. -> server_conf\n\n >>> stop = zc.zkzeo.runzeo.test(server_conf)\n\nThe value is the address to listen on.\n\nWith the configuration above, if we started the server and looked at\nthe ZooKeeper tree for '/databases/demo' using the ``zc.zk`` package, we'd\nsee something like the following::\n\n >>> zk.print_tree('/databases/demo')\n /demo\n /127.0.0.1:64211\n monitor = u'127.0.0.1:11976'\n pid = 5082\n\n.. verify that we can connect to the monitor:\n\n >>> [monitor_addr] = zk.get_children('/databases/demo')\n >>> host, port = monitor_addr.split(':')\n >>> import socket, time\n >>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n >>> sock.settimeout(.5)\n >>> sock.connect((host, int(port)))\n >>> sock.close()\n >>> _ = stop()\n >>> import zc.monitor\n >>> zc.monitor.last_listener.close()\n\nYou can also specify a unix-domain socket name::\n\n \n address 127.0.0.1\n \n\n \n connection zookeeper.example.com:2181\n path /databases/demo\n monitor-server ./monitor.sock\n \n\n \n path demo.fs\n \n\n.. -> server_conf\n\n We need to clear the zc.zk monitor data so we have a clean monitoring\n test below. This is an artifact of running multiple servers in one process.\n\n >>> import zc.zk.monitor\n >>> del zc.zk.monitor._servers[:]\n\n >>> stop = zc.zkzeo.runzeo.test(server_conf)\n\nWhen using a unix-domain socket, the monitor address isn't included in\nthe tree:\n\n >>> zk.print_tree('/databases/demo')\n /demo\n /127.0.0.1:64213\n pid = 5082\n\n.. verify that we can connect to the monitor:\n\n >>> sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n >>> sock.settimeout(.5)\n >>> sock.connect('./monitor.sock')\n\nSome notes on the monitor server:\n\n- A monitor server won't be useful unless you've registered some\n command plugins.\n\n- ``zc.monitor`` isn't a dependency of ``zc.zkzeoc`` and won't\n be in the Python path unless you install it.\n\nMonitoring\n----------\n\nThe zkzeo package provides a Nagios plugin. The plugin takes a\nZooKeeper connection string and path to look up a ZEO server at (using\nthe zc.zk service-registry framework). For example, to monitor the\nserver defined above::\n\n zkzeo-nagios zookeeper.example.com:2181 /databases/demo\n\n.. -> src\n\n >>> import pkg_resources\n >>> monitor = pkg_resources.load_entry_point(\n ... 'zc.zkzeo', 'console_scripts', 'zkzeo-nagios')\n >>> monitor(src.strip().split()[1:])\n Empty storage u'1'\n 1\n\nThe zkzeo nagios monitor supports the same options as the ZEO nagios\nmonitor, so for example to get full metrics::\n\n zkzeo-nagios -m -s statusfile zookeeper.example.com:2181 /databases/demo\n\n.. -> src\n\n >>> monitor(src.strip().split()[1:])\n Empty storage u'1'|active_txns=0\n | connections=0\n waiting=0\n 1\n >>> monitor(src.strip().split()[1:])\n Empty storage u'1'|active_txns=0\n | connections=0\n waiting=0\n aborts=0.0\n commits=0.0\n conflicts=0.0\n conflicts_resolved=0.0\n loads=0.0\n stores=0.0\n 1\n\nSometimes, there may be multiple servers registered at the same path,\nfor example if servers are replicated. When monitoring a single\nserver, you need to know which one to check. If you've a\nmonitor-server for your ZEO process, as we did above, then you can use\nthat to determine which one to use. Just provide the monitor server address::\n\n zkzeo-nagios -m -M ./monitor.sock zookeeper.example.com:2181 /databases/demo\n\n.. -> src\n\n >>> monitor(src.strip().split()[1:])\n Empty storage u'1'|active_txns=0\n | connections=0\n waiting=0\n 1\n\nThere's also a helper function useful for other monitors:\n\n >>> import zc.zkzeo.nagios\n >>> [zc.zkzeo.nagios.find_server(\n ... 'zookeeper.example.com:2181',\n ... '/databases/demo',\n ... None)] == zk.get_children('/databases/demo')\n True\n >>> [zc.zkzeo.nagios.find_server(\n ... 'zookeeper.example.com:2181',\n ... '/databases/demo',\n ... './monitor.sock')] == zk.get_children('/databases/demo')\n True\n\nDefining ZEO clients\n====================\n\nYou can define a client in two ways, from Python and using a\nconfiguration file.\n\nDefining ZEO clients with Python\n--------------------------------\n\nFrom Python, use ``zc.zkzeo.client``::\n\n >>> import zc.zkzeo\n >>> client = zc.zkzeo.client(\n ... 'zookeeper.example.com:2181', '/databases/demo',\n ... max_disconnect_poll=1)\n\nYou pass a ZooKeeper connection string and a path. The ``Client``\nconstructor will create a client storage with addresses found as\nsub-nodes of the given path and it will adjust the client-storage\naddresses as nodes are added and removed as children of the path.\n\nYou can pass all other ``ZEO.ClientStorage.ClientStorage`` arguments,\nexcept the address, as additional positional and keyword arguments.\n\nDatabase and connection convenience functions\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou're usually not really interested in getting a storage object.\nWhat you really want is a database object::\n\n >>> db = zc.zkzeo.DB(\n ... 'zookeeper.example.com:2181', '/databases/demo',\n ... max_disconnect_poll=1)\n\nor often, just a database connection::\n\n >>> conn = zc.zkzeo.connection(\n ... 'zookeeper.example.com:2181', '/databases/demo',\n ... max_disconnect_poll=1)\n\n.. test\n\n >>> exconn = conn\n\nDefining ZEO clients in configuration files\n-------------------------------------------\n\nIn configuration files, use a ``zkzeoclient`` storage\nsection::\n\n %import zc.zkzeo\n\n \n \n zookeeper zookeeper.example.com:2181\n server /databases/demo\n max-disconnect-poll 1\n \n \n\n.. -> conf\n\nThe options for ``zkzeoclient`` are the same as for the standard ZODB\n``zeoclient`` section, except:\n\n- There's an extra required ``zookeeper`` option used to provide a\n ZooKeeper connection string.\n\n- There can be only one ``server`` option and it is used to supply the\n path in ZooKeeper where addresses may be found.\n\n.. test\n\n Double check the clients are working by opening a\n connection and making sure we see changes:\n\n >>> import ZODB.config\n >>> db_from_config = ZODB.config.databaseFromString(conf)\n >>> with db_from_config.transaction() as conn:\n ... conn.root.x = 1\n\n >>> import ZODB\n >>> db_from_py = ZODB.DB(client)\n >>> with db_from_py.transaction() as conn:\n ... print conn.root()\n {'x': 1}\n\n >>> with db.transaction() as conn:\n ... print conn.root()\n {'x': 1}\n\n >>> import transaction\n >>> with transaction.manager:\n ... print exconn.root()\n {'x': 1}\n\n When we stop the storage server, we'll get warnings from zc.zkzeo, the\n clients will disconnect and will have no addresses:\n\n >>> import zope.testing.loggingsupport\n >>> handler = zope.testing.loggingsupport.Handler('zc.zkzeo')\n >>> handler.install()\n\n >>> [old_addr] = zk.get_children('/databases/demo')\n\n >>> stop().exception\n >>> zc.monitor.last_listener.close()\n\n >>> from zope.testing.wait import wait\n >>> wait(lambda : not client.is_connected())\n >>> wait(lambda : not db_from_config.storage.is_connected())\n >>> wait(lambda : not db.storage.is_connected())\n >>> wait(lambda : not exconn.db().storage.is_connected())\n\n >>> print handler\n zc.zkzeo WARNING\n No addresses from \n zc.zkzeo WARNING\n No addresses from \n zc.zkzeo WARNING\n No addresses from \n zc.zkzeo WARNING\n No addresses from \n\n >>> handler.clear()\n\n Looking at the client manager, we see that the address list is now empty:\n\n >>> client._rpc_mgr\n \n\n Let's sleep for a while to make sure we can wake up. Of course, we\n won't sleep *that* long, it's a test.\n\n >>> import time\n >>> time.sleep(9)\n\n Now, we'll restart the server and clients will reconnect\n\n >>> stop = zc.zkzeo.runzeo.test(server_conf)\n\n >>> [addr] = zk.get_children('/databases/demo')\n >>> addr != old_addr\n True\n >>> print zk.export_tree('/databases/demo', ephemeral=True),\n /demo\n /127.0.0.1:56837\n pid = 88841\n\n >>> wait(db_from_config.storage.is_connected)\n >>> with db_from_config.transaction() as conn:\n ... conn.root.x = 2\n >>> wait(db_from_py.storage.is_connected, timeout=22)\n >>> time.sleep(.1)\n >>> with db_from_py.transaction() as conn:\n ... print conn.root()\n {'x': 2}\n\n >>> wait(db.storage.is_connected, timeout=22)\n >>> time.sleep(.1)\n >>> with db.transaction() as conn:\n ... print conn.root()\n {'x': 2}\n\n >>> wait(exconn.db().storage.is_connected, timeout=22)\n >>> time.sleep(.1)\n >>> with transaction.manager:\n ... print exconn.root()\n {'x': 2}\n\n >>> print handler # doctest: +NORMALIZE_WHITESPACE\n zc.zkzeo WARNING\n OK: Addresses from \n zc.zkzeo INFO\n Addresses from :\n ['127.0.0.1:52649']\n zc.zkzeo WARNING\n OK: Addresses from \n zc.zkzeo INFO\n Addresses from :\n ['127.0.0.1:52649']\n zc.zkzeo WARNING\n OK: Addresses from \n zc.zkzeo INFO\n Addresses from :\n ['127.0.0.1:52649']\n zc.zkzeo WARNING\n OK: Addresses from \n zc.zkzeo INFO\n Addresses from :\n ['127.0.0.1:52649']\n\n >>> zk.close()\n >>> handler.uninstall()\n >>> db_from_py.close()\n >>> db_from_config.close()\n >>> db.close()\n >>> exconn.close()\n >>> stop().exception\n >>> zc.monitor.last_listener.close()\n\nChange History\n==============\n\n1.0.1 (2015-01-11)\n------------------\n\nFixed packaging problem (of course).\n\n1.0.0 (2015-01-11)\n------------------\n\n- Updated to work with ZEO/ZODB rather than ZODB3.\n\n- Added a Nagios monitoring plugin, the script zkzeo-nagios\n\n0.3.2 (2012-07-10)\n------------------\n\n- Fixed: Didn't work with explicit configuration of port 0, which is\n recently supported by ZConfig.\n\n0.3.1 (2012-06-26)\n------------------\n\n- Fixed: setting a monitor server on a unix-domain socket didn't work.\n\n0.3.0 (2012-02-07)\n------------------\n\n- Added a static extra to force a dependency on\n ``zc-zookeeper-static``.\n\n- In test mode, use a shorter asyncore loop timeout to make the server\n shut down faster.\n\n- Fixed: zc.zkzeo depended on ``zc.zk [static]``, which forced\n installation of ``zc-zookeeper-static``, which should be optional.\n\n- Fixed: tests didn't pass with a recent change in handling of\n registration with empty host names in ``zc.zk``.\n\n- Fixed: Packaging: distribute can't install distributions with\n symlinks, so stopped using symlinks in distribution.\n\n0.2.1 (2011-12-14)\n------------------\n\n- Fixed bug: The ``path`` key on the ``zookeeper``\n server-configuration section was required, and shouldn't have been.\n\n0.2.0 (2011-12-13)\n------------------\n\n- Register the host name from the ZEO address setting with ZooKeeper.\n (This is often an empty string, which ``zc.zk`` turns into the\n fully-quelified domain name.)\n\n- Fixed bug in handling the monitor-server. The actuall address\n setting was ignored.\n\n0.1.1 (2011-12-12)\n------------------\n\n- Fixed a packaging bug.\n\n0.1.0 (2011-12-11)\n------------------\n\nInitial release.",
"description_content_type": null,
"docs_url": null,
"download_url": "UNKNOWN",
"downloads": {
"last_day": -1,
"last_month": -1,
"last_week": -1
},
"home_page": "UNKNOWN",
"keywords": null,
"license": "ZPL 2.1",
"maintainer": null,
"maintainer_email": null,
"name": "zc.zkzeo",
"package_url": "https://pypi.org/project/zc.zkzeo/",
"platform": "UNKNOWN",
"project_url": "https://pypi.org/project/zc.zkzeo/",
"project_urls": {
"Download": "UNKNOWN",
"Homepage": "UNKNOWN"
},
"release_url": "https://pypi.org/project/zc.zkzeo/1.0.1/",
"requires_dist": null,
"requires_python": null,
"summary": "ZEO ZooKeeper",
"version": "1.0.1"
},
"last_serial": 1378507,
"releases": {
"0.1.0": [
{
"comment_text": "",
"digests": {
"md5": "c405cbefdb4ddf55e52191fd6beb6cab",
"sha256": "c2f7ce61df7943ae213e52a87d7be93158ff80b259849e305fceec9f9bcb00ea"
},
"downloads": -1,
"filename": "zc.zkzeo-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "c405cbefdb4ddf55e52191fd6beb6cab",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 10055,
"upload_time": "2011-12-11T20:00:02",
"url": "https://files.pythonhosted.org/packages/8c/2a/1d724e8d9400d685aade1d4395f4b4aacff1e3cdc62c10916ed616c4b105/zc.zkzeo-0.1.0.tar.gz"
}
],
"0.1.1": [
{
"comment_text": "",
"digests": {
"md5": "426f0a3900974e40ad1c3f061c29d943",
"sha256": "52b30aa40bb9134b538a22bd664c6fdebb8ad11374c09f7b74a5228a83c81bbd"
},
"downloads": -1,
"filename": "zc.zkzeo-0.1.1.tar.gz",
"has_sig": false,
"md5_digest": "426f0a3900974e40ad1c3f061c29d943",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 10105,
"upload_time": "2011-12-12T15:29:54",
"url": "https://files.pythonhosted.org/packages/2e/98/df77618f6bd21b5a95d6bbfddd9dd1c7e1522edefca07509858221876fd4/zc.zkzeo-0.1.1.tar.gz"
}
],
"0.2.0": [
{
"comment_text": "",
"digests": {
"md5": "e9fcf104ae0780dd4ceeb7c5d8305d6a",
"sha256": "bad9e663844daa9e273eb98e5e94dae79b098267b47e84f5b764a3ecdd405c44"
},
"downloads": -1,
"filename": "zc.zkzeo-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "e9fcf104ae0780dd4ceeb7c5d8305d6a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 11304,
"upload_time": "2011-12-13T21:27:59",
"url": "https://files.pythonhosted.org/packages/09/40/b375435f1fdcf56991d2d19107a91b74315112e6c25961109f90496f3cac/zc.zkzeo-0.2.0.tar.gz"
}
],
"0.2.1": [
{
"comment_text": "",
"digests": {
"md5": "b7472db5317d0450055c5ed4cf422bbd",
"sha256": "c38e26e23fc3488f65cc2ba6311cf588ba30efef00a35a707b96e46f66a62a03"
},
"downloads": -1,
"filename": "zc.zkzeo-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "b7472db5317d0450055c5ed4cf422bbd",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 11472,
"upload_time": "2011-12-14T16:56:05",
"url": "https://files.pythonhosted.org/packages/29/34/95c310ad092b2023376c7ef2ef4c3790de74859512f35f3d4a5547bbd2f0/zc.zkzeo-0.2.1.tar.gz"
}
],
"0.3.0": [
{
"comment_text": "",
"digests": {
"md5": "adafa2cb63b5f8a35e03c4cadc6e823e",
"sha256": "6a089c167137295d15552a708e8743c82169cc8fef08c31d848c6eaf3e27b753"
},
"downloads": -1,
"filename": "zc.zkzeo-0.3.0.tar.gz",
"has_sig": false,
"md5_digest": "adafa2cb63b5f8a35e03c4cadc6e823e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 12760,
"upload_time": "2012-02-07T20:10:34",
"url": "https://files.pythonhosted.org/packages/34/23/8ddff42168cfd283239d0a76034e452c3709656c670138f59d80560c00e5/zc.zkzeo-0.3.0.tar.gz"
}
],
"0.3.1": [
{
"comment_text": "",
"digests": {
"md5": "4e0d82ab978c8dbcc796a518ffd79d7e",
"sha256": "2d29fef24624e7eafff9dfd1fbb798ca74079c224abad3b2b6e75d2d61504520"
},
"downloads": -1,
"filename": "zc.zkzeo-0.3.1.tar.gz",
"has_sig": false,
"md5_digest": "4e0d82ab978c8dbcc796a518ffd79d7e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 13645,
"upload_time": "2012-06-26T13:53:03",
"url": "https://files.pythonhosted.org/packages/02/5e/0b977bad8420c4f76d0e44972f9ab4a95be73c8515a81cd0e0671a52d116/zc.zkzeo-0.3.1.tar.gz"
}
],
"0.3.2": [
{
"comment_text": "",
"digests": {
"md5": "ffc952313473533ada3a6e3ed37dbbc6",
"sha256": "3cd205c2707fc8a3a2f063fddeca123f30c72f2043c91b1d36457025e08ef48c"
},
"downloads": -1,
"filename": "zc.zkzeo-0.3.2.tar.gz",
"has_sig": false,
"md5_digest": "ffc952313473533ada3a6e3ed37dbbc6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 14869,
"upload_time": "2012-07-10T22:08:02",
"url": "https://files.pythonhosted.org/packages/db/df/5a8ae15be72ddcf8724c78bdc3e6c23ddcb76ec3cc5331399044b0507951/zc.zkzeo-0.3.2.tar.gz"
}
],
"1.0.0": [
{
"comment_text": "",
"digests": {
"md5": "e0cbe770a27355618ed9c9a6ae6e8add",
"sha256": "0888c594bc6a4492d5276d3a9ae854c167ac085ac06994485e8c4df79cfe870e"
},
"downloads": -1,
"filename": "zc.zkzeo-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "e0cbe770a27355618ed9c9a6ae6e8add",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15514,
"upload_time": "2015-01-11T15:18:19",
"url": "https://files.pythonhosted.org/packages/db/e6/50e056e4e7c12255864782b4919f4f5a8f1e7ad7dd39ae5847d63ca5b4eb/zc.zkzeo-1.0.0.tar.gz"
}
],
"1.0.1": [
{
"comment_text": "",
"digests": {
"md5": "2ab587168a68ee37356fb61fc22f360c",
"sha256": "22ed28a947125f0862c4cabe5d9dfb8a0bfa8c3f2e1ad2877f4e72e53e2aab55"
},
"downloads": -1,
"filename": "zc.zkzeo-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "2ab587168a68ee37356fb61fc22f360c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15869,
"upload_time": "2015-01-11T15:26:28",
"url": "https://files.pythonhosted.org/packages/56/05/2d9c476eb2273c770a9d00c817188b85b1a8a8d0e0286ba37c5027ec7d18/zc.zkzeo-1.0.1.tar.gz"
}
]
},
"urls": [
{
"comment_text": "",
"digests": {
"md5": "2ab587168a68ee37356fb61fc22f360c",
"sha256": "22ed28a947125f0862c4cabe5d9dfb8a0bfa8c3f2e1ad2877f4e72e53e2aab55"
},
"downloads": -1,
"filename": "zc.zkzeo-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "2ab587168a68ee37356fb61fc22f360c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 15869,
"upload_time": "2015-01-11T15:26:28",
"url": "https://files.pythonhosted.org/packages/56/05/2d9c476eb2273c770a9d00c817188b85b1a8a8d0e0286ba37c5027ec7d18/zc.zkzeo-1.0.1.tar.gz"
}
]
}