[Checkins] SVN: zc.zk/trunk/s - Added support for discovering and testing ephemeral addresses using

jim cvs-admin at zope.org
Fri Jun 22 15:28:05 UTC 2012


Log message for revision 127018:
  - Added support for discovering and testing ephemeral addresses using
    zc.monitor.  See ``monitor.test`` for details.
  

Changed:
  U   zc.zk/trunk/setup.py
  U   zc.zk/trunk/src/zc/zk/README.txt
  A   zc.zk/trunk/src/zc/zk/monitor.py
  A   zc.zk/trunk/src/zc/zk/monitor.test
  A   zc.zk/trunk/src/zc/zk/monitor.zcml
  U   zc.zk/trunk/src/zc/zk/tests.py

-=-
Modified: zc.zk/trunk/setup.py
===================================================================
--- zc.zk/trunk/setup.py	2012-06-22 13:31:09 UTC (rev 127017)
+++ zc.zk/trunk/setup.py	2012-06-22 15:28:01 UTC (rev 127018)
@@ -16,7 +16,7 @@
 install_requires = ['setuptools', 'zc.thread']
 extras_require = dict(
     test=['zope.testing', 'zc-zookeeper-static', 'mock', 'manuel',
-          'zope.event', 'netifaces'],
+          'zope.event', 'netifaces', 'zope.component', 'zc.monitor'],
     static=['zc-zookeeper-static'],
     )
 

Modified: zc.zk/trunk/src/zc/zk/README.txt
===================================================================
--- zc.zk/trunk/src/zc/zk/README.txt	2012-06-22 13:31:09 UTC (rev 127017)
+++ zc.zk/trunk/src/zc/zk/README.txt	2012-06-22 15:28:01 UTC (rev 127018)
@@ -1165,12 +1165,15 @@
 Change History
 ==============
 
-0.9.0 (2012-06-21)
+0.9.0 (2012-06-22)
 ------------------
 
-- Fixed: The ZooKeeper logging sometimes generated lots of spurious
-  empty log messages.
+- Added support for discovering and testing ephemeral addresses using
+  zc.monitor.  See ``monitor.test`` for details.
 
+- Fixed: The ZooKeeper logging bridge sometimes generated lots of
+  spurious empty log messages.
+
 0.8.0 (2012-05-15)
 ------------------
 

Added: zc.zk/trunk/src/zc/zk/monitor.py
===================================================================
--- zc.zk/trunk/src/zc/zk/monitor.py	                        (rev 0)
+++ zc.zk/trunk/src/zc/zk/monitor.py	2012-06-22 15:28:01 UTC (rev 127018)
@@ -0,0 +1,73 @@
+##############################################################################
+#
+# Copyright (c) 2011 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 json
+import sys
+
+_servers = []
+
+def notify(event):
+    _servers.append(dict(address=event.name, path=event.path,
+                         **event.properties))
+
+def servers(connection, path=None):
+    if path is None:
+        connection.write(json.dumps(_servers) + '\n')
+    else:
+        connection.write(
+            ' '.join([s['address'] for s in _servers if s['path'] == path])
+             + '\n')
+
+def _connect(addr):
+    import re
+    import socket
+
+    if re.search(':\d+$', addr):
+        host, port = addr.rsplit(':')
+        addr = host, int(port)
+        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    else:
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+
+    sock.connect(addr)
+    return sock
+
+def check(args=None):
+    if args is None:
+        args = sys.argv[1:]
+
+    [addr, path] = args
+
+    sock = _connect(addr)
+
+    sock.sendall('servers %s\n' % path)
+    f = sock.makefile()
+    addr = f.readline()
+
+    f.close()
+    sock.close()
+
+    _connect(addr).close()
+
+def get_addr(args=None):
+    if args is None:
+        args = sys.argv[1:]
+
+
+    [addr, path] = args
+
+    sock = _connect(addr)
+    f = sock.makefile()
+    sock.sendall('servers %s\n' % path)
+    print f.readline(),


Property changes on: zc.zk/trunk/src/zc/zk/monitor.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: zc.zk/trunk/src/zc/zk/monitor.test
===================================================================
--- zc.zk/trunk/src/zc/zk/monitor.test	                        (rev 0)
+++ zc.zk/trunk/src/zc/zk/monitor.test	2012-06-22 15:28:01 UTC (rev 127018)
@@ -0,0 +1,99 @@
+zc.monitor plugin for reportint on servers registered by a process
+==================================================================
+
+Sometimes, when deploying a process that registers servers listening
+on ephemeral ports, we need to be able to find out what the parts
+(addresses) are.  Looking at the ZooKeeper tree may not be convenient
+if there are multiple servers.
+
+Th zc.zk.monitor modules provides a zc.monitor plugin that can be
+subscribed to zc.zk.RegisteringServer events and then used in a
+zc.monitor server to report on registered servers.
+
+    >>> import sys, zc.zk.monitor, zc.zk
+
+    >>> zc.zk.monitor.notify(zc.zk.RegisteringServer(
+    ...     '1.2.3.4:8080', '/foo/bar', dict(pid=42)))
+
+    >>> zc.zk.monitor.servers(sys.stdout)
+    [{"path": "/foo/bar", "pid": 42, "address": "1.2.3.4:8080"}]
+
+It outputs a list of server objects as a JSON string.
+
+    >>> zc.zk.monitor.notify(zc.zk.RegisteringServer(
+    ...     '1.2.3.4:8081', '/foo/baz', dict(pid=42)))
+
+    >>> zc.zk.monitor.servers(sys.stdout) # doctest: +NORMALIZE_WHITESPACE
+    [{"path": "/foo/bar", "pid": 42, "address": "1.2.3.4:8080"},
+     {"path": "/foo/baz", "pid": 42, "address": "1.2.3.4:8081"}]
+
+If you specify a path, then only the address with that path will be
+output as a string (not json):
+
+    >>> zc.zk.monitor.servers(sys.stdout, '/foo/bar')
+    1.2.3.4:8080
+
+Helper scripts
+==============
+
+``zc.zk.monitor`` provides two helper scripts.  They aren't registered
+as setuptools entry points, as they are only useful for servers that
+use zc.monitor.
+
+zc.zk.monitor.check
+-------------------
+
+The check script (entry-point) takes a monitor address and a path,
+connects to the monitor server to get the address registered for a
+monitor, and connects to the address.  This can be used to check
+whether a server is up and running (or at least accepting
+connections).
+
+We'll test it by starting a server, registering it and checking it:
+
+    >>> import socket, zc.monitor, zc.thread, sys
+    >>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    >>> s.bind(('', 0))
+    >>> s.listen(1)
+
+    >>> _, server_port = s.getsockname()
+    >>> _, monitor_port = zc.monitor.start(('', 0))
+    >>> zc.monitor.register(zc.zk.monitor.servers, 'servers')
+    >>> zc.zk.monitor.notify(zc.zk.RegisteringServer(
+    ...     ':%s' % server_port, '/test/server', dict(pid=42)))
+
+    >>> zc.zk.monitor.check((':%s /test/server' % monitor_port).split())
+
+Here, check simply returned.  Now, if we stop our server:
+
+    >>> s.close()
+
+check will error:
+
+    >>> zc.zk.monitor.check((':%s /test/server' % monitor_port).split())
+    Traceback (most recent call last):
+    ...
+    error: [Errno 111] Connection refused
+
+This will, of course, cause it to exit with a non-zero status when run
+as an actual script.
+
+zc.zk.monitor.get_addr
+----------------------
+
+The get_addrscript simply prints the address it got from the monitor:
+
+    >>> zc.zk.monitor.get_addr((':%s /test/server' % monitor_port).split())
+    :37327
+
+This can be used to get the address to pass it to some other process.
+
+.. cleanup
+
+    >>> import zope.component
+    >>> zope.component.getSiteManager().unregisterUtility(
+    ...     zc.zk.monitor.servers,
+    ...     zc.monitor.interfaces.IMonitorPlugin, 'servers')
+    True
+
+    >>> zc.monitor.last_listener.close()


Property changes on: zc.zk/trunk/src/zc/zk/monitor.test
___________________________________________________________________
Added: svn:eol-style
   + native

Added: zc.zk/trunk/src/zc/zk/monitor.zcml
===================================================================
--- zc.zk/trunk/src/zc/zk/monitor.zcml	                        (rev 0)
+++ zc.zk/trunk/src/zc/zk/monitor.zcml	2012-06-22 15:28:01 UTC (rev 127018)
@@ -0,0 +1,12 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+<include package="zope.component" />
+
+<subscriber for="zc.zk.RegisteringServer" handler="zc.zk.monitor.notify" />
+
+<utility provides="zc.monitor.interfaces.IMonitorPlugin"
+         name="servers"
+         component="zc.zk.monitor.servers"
+         />
+
+</configure>


Property changes on: zc.zk/trunk/src/zc/zk/monitor.zcml
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: zc.zk/trunk/src/zc/zk/tests.py
===================================================================
--- zc.zk/trunk/src/zc/zk/tests.py	2012-06-22 13:31:09 UTC (rev 127017)
+++ zc.zk/trunk/src/zc/zk/tests.py	2012-06-22 15:28:01 UTC (rev 127018)
@@ -1557,6 +1557,12 @@
             setUp=zc.zk.testing.setUp, tearDown=zc.zk.testing.tearDown,
             checker=checker,
             ),
+        doctest.DocFileSuite(
+            'monitor.test',
+            checker = zope.testing.renormalizing.RENormalizing([
+                (re.compile(':\d+'), ':9999'),
+                ])
+            ),
         ))
     if not zc.zk.testing.testing_with_real_zookeeper():
         suite.addTest(unittest.makeSuite(Tests))



More information about the checkins mailing list