[Checkins] SVN: Sandbox/J1m/zkzopeserver/ zope.server wrapper that registers w ZooKeeper
Jim Fulton
jim at zope.com
Sat Dec 10 23:26:03 UTC 2011
Log message for revision 123671:
zope.server wrapper that registers w ZooKeeper
Changed:
D Sandbox/J1m/zkzopeserver/README.txt
A Sandbox/J1m/zkzopeserver/README.txt
U Sandbox/J1m/zkzopeserver/buildout.cfg
U Sandbox/J1m/zkzopeserver/setup.py
A Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/
A Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/README.txt
A Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/__init__.py
A Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/tests.py
-=-
Deleted: Sandbox/J1m/zkzopeserver/README.txt
===================================================================
--- Sandbox/J1m/zkzopeserver/README.txt 2011-12-10 23:20:48 UTC (rev 123670)
+++ Sandbox/J1m/zkzopeserver/README.txt 2011-12-10 23:26:03 UTC (rev 123671)
@@ -1,14 +0,0 @@
-Title Here
-**********
-
-
-To learn more, see
-
-
-Changes
-*******
-
-0.1.0 (yyyy-mm-dd)
-==================
-
-Initial release
Added: Sandbox/J1m/zkzopeserver/README.txt
===================================================================
--- Sandbox/J1m/zkzopeserver/README.txt (rev 0)
+++ Sandbox/J1m/zkzopeserver/README.txt 2011-12-10 23:26:03 UTC (rev 123671)
@@ -0,0 +1 @@
+link src/zc/zkzopeserver/README.txt
\ No newline at end of file
Property changes on: Sandbox/J1m/zkzopeserver/README.txt
___________________________________________________________________
Added: svn:special
+ *
Modified: Sandbox/J1m/zkzopeserver/buildout.cfg
===================================================================
--- Sandbox/J1m/zkzopeserver/buildout.cfg 2011-12-10 23:20:48 UTC (rev 123670)
+++ Sandbox/J1m/zkzopeserver/buildout.cfg 2011-12-10 23:26:03 UTC (rev 123671)
@@ -1,12 +1,27 @@
[buildout]
-develop = .
-parts = test py
+develop = . zk
+parts = test py paste.ini
[test]
recipe = zc.recipe.testrunner
-eggs =
+eggs = zc.zkzopeserver [test]
[py]
recipe = zc.recipe.egg
eggs = ${test:eggs}
+ PasteScript
+ bobo
+
interpreter = py
+
+[paste.ini]
+recipe = zc.recipe.deployment:configuration
+text =
+ [app:main]
+ use = egg:bobo
+ bobo_resources = zc.zkzopeserver.tests
+
+ [server:main]
+ use = egg:zc.zkzopeserver
+ zookeeper = 127.0.0.1:2181
+ path = /
Modified: Sandbox/J1m/zkzopeserver/setup.py
===================================================================
--- Sandbox/J1m/zkzopeserver/setup.py 2011-12-10 23:20:48 UTC (rev 123670)
+++ Sandbox/J1m/zkzopeserver/setup.py 2011-12-10 23:26:03 UTC (rev 123671)
@@ -11,12 +11,14 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-name, version = 'zc.', '0'
+name, version = 'zc.zkzopeserver', '0'
-install_requires = ['setuptools']
-extras_require = dict(test=['zope.testing'])
+install_requires = ['setuptools', 'zc.zk', 'zope.server']
+extras_require = dict(test=['zope.testing', 'zc.zk [static,test]'])
entry_points = """
+[paste.server_runner]
+main = zc.zkzopeserver:run
"""
from setuptools import setup
@@ -28,7 +30,7 @@
name = name, version = version,
long_description=open('README.txt').read(),
- description = open('README.txt').read().strip().split('\n')[0],
+ description = open('README.txt').read().strip().split('\n')[1],
packages = [name.split('.')[0], name],
namespace_packages = [name.split('.')[0]],
package_dir = {'': 'src'},
Added: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/README.txt
===================================================================
--- Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/README.txt (rev 0)
+++ Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/README.txt 2011-12-10 23:26:03 UTC (rev 123671)
@@ -0,0 +1,93 @@
+=================================================
+zope.server wrapper that registers with ZooKeeper
+=================================================
+
+``zc.zkzopeserver`` provides a wrapper for the zope.server WSGI runner
+that registers with ZooKeeper. By registering with ZooKeeper, you can
+let the operating system assign ports and have clients find your
+server by looking in ZooKeeper.
+
+Basic Usage
+===========
+
+The wrapper is used in a past-deply configuration file::
+
+ [server:main]
+ use = egg:zc.zkzopeserver
+ zookeeper = zookeeper.example.com:2181
+ path = /fooservice/providers
+
+.. -> server_config
+
+The wrapper supports the following options:
+
+zookeeper
+ required ZooKeeper connection string
+
+path
+ required path at which to register your server.
+
+ Your server is registered by adding a ZooKeeper ephemeral node as a
+ child of the path with the server address as the name.
+
+host
+ host name or ip to listen on, defaultiong to ''
+
+port
+ The port to listen on, defaulting to 0
+
+session_timeout
+ A ZooKeeper session timeout in milliseconds
+
+threads
+ The size of the thread pool, defaulting to 1
+
+.. test
+
+ >>> import ConfigParser, StringIO
+ >>> parser = ConfigParser.RawConfigParser()
+ >>> parser.readfp(StringIO.StringIO(server_config))
+ >>> kw = dict(parser.items('server:main'))
+
+ >>> import pkg_resources
+ >>> dist = kw.pop('use').split(':')[1]
+ >>> [run] = [v.load()
+ ... for v in pkg_resources.get_entry_map(
+ ... 'zc.zkzopeserver', 'paste.server_runner'
+ ... ).values()]
+
+ >>> import wsgiref.simple_server, zc.thread
+ >>> @zc.thread.Thread
+ ... def server():
+ ... run(wsgiref.simple_server.demo_app, {}, **kw)
+
+ >>> import time
+ >>> time.sleep(.1)
+
+ >>> import urllib, zc.zk
+ >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
+
+ >>> [port] = [int(c.split(':')[1])
+ ... for c in zk.get_children('/fooservice/providers')]
+ >>> print urllib.urlopen('http://127.0.0.1:%s/' % port).read()
+ ... # doctest: +ELLIPSIS
+ Hello world!
+ ...
+
+ Cleanup, sigh, violently close the server.
+
+ >>> import asyncore
+ >>> for s in asyncore.socket_map.values():
+ ... s.close()
+ >>> server.join(1)
+ >>> zk.close()
+
+
+
+Change History
+==============
+
+0.1.0 (2011-12-??)
+------------------
+
+Initial release
Property changes on: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/README.txt
___________________________________________________________________
Added: svn:eol-style
+ native
Added: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/__init__.py
===================================================================
--- Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/__init__.py (rev 0)
+++ Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/__init__.py 2011-12-10 23:26:03 UTC (rev 123671)
@@ -0,0 +1,38 @@
+##############################################################################
+#
+# Copyright Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import asyncore
+import zc.zk
+import zope.server.taskthreads
+import zope.server.http.wsgihttpserver
+
+def run(wsgi_app, global_conf,
+ zookeeper, path, session_timeout=None,
+ name=__name__, host='', port=0, threads=1,
+ ):
+ port = int(port)
+ threads = int(threads)
+
+ task_dispatcher = zope.server.taskthreads.ThreadedTaskDispatcher()
+ task_dispatcher.setThreadCount(threads)
+ server = zope.server.http.wsgihttpserver.WSGIHTTPServer(
+ wsgi_app, name, host, port,
+ task_dispatcher=task_dispatcher)
+ server.ZooKeeper = zc.zk.ZooKeeper(
+ zookeeper, session_timeout and int(session_timeout))
+ server.ZooKeeper.register_server(
+ path, "%s:%s" % server.socket.getsockname())
+ try:
+ asyncore.loop()
+ finally:
+ server.ZooKeeper.close()
Property changes on: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/__init__.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: svn:eol-style
+ native
Added: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/tests.py
===================================================================
--- Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/tests.py (rev 0)
+++ Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/tests.py 2011-12-10 23:26:03 UTC (rev 123671)
@@ -0,0 +1,126 @@
+##############################################################################
+#
+# Copyright Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import asyncore
+import doctest
+import manuel.capture
+import manuel.doctest
+import manuel.testing
+import re
+import time
+import unittest
+import urllib
+import zc.thread
+import zc.zk.testing
+import zope.testing.renormalizing
+
+maxactive = active = 0
+def reset():
+ global active, maxactive
+ r = maxactive
+ maxactive = active = 0
+ return r
+def slow_app(environ, start_response):
+ global active, maxactive
+ active += 1
+ maxactive = max(maxactive, active)
+ status = '200 OK'
+ response_headers = [('Content-type', 'text/plain')]
+ time.sleep(.1)
+ start_response(status, response_headers)
+ active -= 1
+ return ['Hello world!\n']
+
+def stop_server(thread):
+ for s in asyncore.socket_map.values():
+ s.close()
+ asyncore.socket_map.clear()
+ thread.join(1)
+
+def test_options():
+ """
+ Make sure various advertized options work:
+
+ >>> @zc.thread.Thread
+ ... def server():
+ ... zc.zkzopeserver.run(
+ ... slow_app, {},
+ ... zookeeper='zookeeper.example.com:2181',
+ ... path='/fooservice/providers',
+ ... session_timeout='4242',
+ ... host='127.0.0.1',
+ ... port='3042',
+ ... threads='3',
+ ... )
+
+ >>> time.sleep(.1)
+ >>> zk = zc.zk.ZooKeeper('zookeeper.example.com:2181')
+
+ Did it get registered with the given host and port?
+
+ >>> zk.print_tree('/fooservice/providers')
+ /providers
+ /127.0.0.1:3042
+ pid = 3699
+
+ How many can we do at once? Should be 3
+
+ >>> [url] = [('http://%s/' % addr)
+ ... for addr in zk.get_children('/fooservice/providers')]
+
+ >>> def get():
+ ... f = urllib.urlopen(url)
+ ... if not f.read().startwith('Hello world!'):
+ ... print '?'
+ ... f.close()
+
+ >>> _ = reset()
+ >>> threads = [zc.thread.Thread(get) for i in range(6)]
+ >>> _ = [t.join() for t in threads]
+
+ >>> reset()
+ 3
+
+ Did session_timeout get passed? If we're using the mock ZooKeeper,
+ we camn tell:
+
+ >>> if ZooKeeper is not None:
+ ... ZooKeeper.recv_timeout(0)
+ 4242
+
+ When the server stops, it's unregistered:
+
+ >>> stop_server(server)
+ >>> zk.print_tree('/fooservice/providers')
+ /providers
+
+ >>> zk.close()
+ """
+
+
+def test_suite():
+ checker = zope.testing.renormalizing.RENormalizing([
+ (re.compile('pid = \d+'), 'pid = 9999'),
+ ])
+ suite = unittest.TestSuite((
+ manuel.testing.TestSuite(
+ manuel.doctest.Manuel(checker=checker) + manuel.capture.Manuel(),
+ 'README.txt',
+ setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
+ ),
+ doctest.DocTestSuite(
+ setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
+ checker=checker,
+ ),
+ ))
+ return suite
Property changes on: Sandbox/J1m/zkzopeserver/src/zc/zkzopeserver/tests.py
___________________________________________________________________
Added: svn:keywords
+ Id
Added: svn:eol-style
+ native
More information about the checkins
mailing list