[Checkins] SVN: zc.sshtunnel/trunk/ basic recipe to manage an SSH
tunnel in a development buildout
Fred L. Drake, Jr.
fdrake at gmail.com
Mon Feb 26 12:15:20 EST 2007
Log message for revision 72824:
basic recipe to manage an SSH tunnel in a development buildout
Changed:
_U zc.sshtunnel/trunk/
A zc.sshtunnel/trunk/buildout.cfg
A zc.sshtunnel/trunk/setup.py
A zc.sshtunnel/trunk/src/
A zc.sshtunnel/trunk/src/zc/
A zc.sshtunnel/trunk/src/zc/__init__.py
A zc.sshtunnel/trunk/src/zc/sshtunnel/
A zc.sshtunnel/trunk/src/zc/sshtunnel/README.txt
A zc.sshtunnel/trunk/src/zc/sshtunnel/__init__.py
A zc.sshtunnel/trunk/src/zc/sshtunnel/recipe.py
A zc.sshtunnel/trunk/src/zc/sshtunnel/tests.py
-=-
Property changes on: zc.sshtunnel/trunk
___________________________________________________________________
Name: svn:ignore
+ .installed.cfg
bin
develop-eggs
eggs
parts
Added: zc.sshtunnel/trunk/buildout.cfg
===================================================================
--- zc.sshtunnel/trunk/buildout.cfg 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/buildout.cfg 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,9 @@
+[buildout]
+develop = .
+parts = test
+
+find-links = http://download.zope.org/distribution/
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.sshtunnel [test]
Property changes on: zc.sshtunnel/trunk/buildout.cfg
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/setup.py
===================================================================
--- zc.sshtunnel/trunk/setup.py 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/setup.py 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,20 @@
+from setuptools import setup
+
+entry_points = """\
+
+[zc.buildout]
+default=zc.sshtunnel.recipe:Recipe
+
+"""
+
+setup(
+ name="zc.sshtunnel",
+ packages=["zc.sshtunnel"],
+ package_dir={"": "src"},
+ namespace_packages=["zc"],
+ install_requires=["setuptools"],
+ entry_points=entry_points,
+ extras_require={"test": "zc.buildout"},
+ include_package_data=True,
+ zip_safe=False,
+ )
Property changes on: zc.sshtunnel/trunk/setup.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/src/zc/__init__.py
===================================================================
--- zc.sshtunnel/trunk/src/zc/__init__.py 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/src/zc/__init__.py 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,7 @@
+# This directory is a Python namespace package.
+try:
+ import pkg_resources
+ pkg_resources.declare_namespace(__name__)
+except ImportError:
+ import pkgutil
+ __path__ = pkgutil.extend_path(__path__, __name__)
Property changes on: zc.sshtunnel/trunk/src/zc/__init__.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/src/zc/sshtunnel/README.txt
===================================================================
--- zc.sshtunnel/trunk/src/zc/sshtunnel/README.txt 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/src/zc/sshtunnel/README.txt 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,58 @@
+=================================
+Creating SSH tunnels in buildouts
+=================================
+
+This recipe creates a control script for an SSH tunnel. This is only
+expected to work on systems with the OpenSSH "ssh" binary on $PATH,
+and may require setting up the SSH configuration to use the expected
+usernames for each system.
+
+Let's create a configuration that defines a single tunnel in a part
+called "my-tunnel"::
+
+ >>> write("buildout.cfg", """\
+ ...
+ ... [buildout]
+ ... parts = my-tunnel
+ ... find-links = http://download.zope.org/distribution/
+ ...
+ ... [my-tunnel]
+ ... recipe = zc.sshtunnel
+ ... python = sample-python
+ ... specification = 8080:server.example.net:6060
+ ... via = somehost.example.net
+ ...
+ ... [sample-python]
+ ... executable = /usr/bin/python
+ ...
+ ... """)
+
+Building this out creates a single script in the bin/ directory::
+
+ >>> print system(join("bin", "buildout")),
+ buildout: Installing my-tunnel
+
+ >>> ls("bin")
+ - buildout
+ - my-tunnel
+
+The script is a Python script; the tunnel parameters are stored at the
+top of the script::
+
+ >>> cat(join("bin", "my-tunnel"))
+ #!/usr/bin/python
+ ...
+ pid_file = "/sample-buildout/parts/my-tunnel.pid"
+ specification = "8080:server.example.net:6060"
+ via = "somehost.example.net"
+ wait_port = 8080
+ name = "my-tunnel"
+ ...
+
+The script accepts the "start", "stop", "restart", and "status"
+verbs. Let's demonstrate "status", since that doesn't require
+actually establishing a tunnel::
+
+ >>> print system(join("bin", "my-tunnel") + " status")
+ Pid file /sample-buildout/parts/my-tunnel.pid doesn't exist
+ <BLANKLINE>
Property changes on: zc.sshtunnel/trunk/src/zc/sshtunnel/README.txt
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/src/zc/sshtunnel/__init__.py
===================================================================
--- zc.sshtunnel/trunk/src/zc/sshtunnel/__init__.py 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/src/zc/sshtunnel/__init__.py 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1 @@
+# This directory is a Python package.
Property changes on: zc.sshtunnel/trunk/src/zc/sshtunnel/__init__.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/src/zc/sshtunnel/recipe.py
===================================================================
--- zc.sshtunnel/trunk/src/zc/sshtunnel/recipe.py 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/src/zc/sshtunnel/recipe.py 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,144 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""\
+`zc.buildout` recipe to create and manage an SSH tunnel using an rc script.
+
+"""
+__docformat__ = "reStructuredText"
+
+import os
+
+
+class Recipe(object):
+
+ def __init__(self, buildout, name, options):
+ self.name = name
+ self.options = options
+
+ self.via = options["via"]
+ self.specification = options["specification"]
+ parts = self.specification.split(":")
+ wait_port = int(parts[-3])
+ self.wait_port = str(wait_port)
+
+ python = options.get("python", "buildout")
+ self.executable = buildout[python]["executable"]
+
+ self.script = os.path.join(
+ buildout["buildout"]["bin-directory"], name)
+ self.pidfile = os.path.join(
+ buildout["buildout"]["parts-directory"], name + ".pid")
+
+ options["executable"] = self.executable
+ options["pidfile"] = self.pidfile
+ options["run-script"] = self.script
+
+ def install(self):
+ d = {
+ "name": self.name,
+ "pid_file": self.pidfile,
+ "python": self.executable,
+ "specification": self.specification,
+ "via": self.via,
+ "wait_port": self.wait_port,
+ }
+ text = tunnel_script_template % d
+ f = open(self.script, "w")
+ f.write(text)
+ f.close()
+ os.chmod(self.script, int("0770", 8))
+ return [self.script]
+
+
+tunnel_script_template = r"""#!%(python)s
+
+import os, sys, signal, socket, time, errno
+
+pid_file = "%(pid_file)s"
+specification = "%(specification)s"
+via = "%(via)s"
+wait_port = %(wait_port)s
+name = "%(name)s"
+
+def wait(port):
+ addr = 'localhost', port
+ for i in range(120):
+ time.sleep(0.25)
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(addr)
+ s.close()
+ break
+ except socket.error, e:
+ if e[0] not in (errno.ECONNREFUSED, errno.ECONNRESET):
+ raise
+ s.close()
+ else:
+ raise
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ [verb] = args
+
+ if verb == 'start':
+ if os.path.exists(pid_file):
+ print "Pid file %%s already exists" %% pid_file
+ return
+
+ pid = os.fork()
+ if pid == 0:
+ # redirect output to /dev/null. This will
+ # cause nohup to be unannoying
+ os.dup2(os.open('/dev/null', os.O_WRONLY), 1)
+ os.dup2(os.open('/dev/null', os.O_WRONLY), 2)
+ pid = os.spawnlp(os.P_NOWAIT, 'nohup', 'nohup',
+ 'ssh', '-TnaxqNL'+specification, via)
+ open(pid_file, 'w').write("%%s\n" %% pid)
+ else:
+ wait(wait_port)
+ print name, 'started'
+ elif verb == 'status':
+ if os.path.exists(pid_file):
+ pid = int(open(pid_file).read().strip())
+ try:
+ os.kill(pid, 0)
+ except OSError, v:
+ print v
+ else:
+ print name, 'running'
+ else:
+ print "Pid file %%s doesn't exist" %% pid_file
+ elif verb == 'stop':
+ if os.path.exists(pid_file):
+ pid = int(open(pid_file).read().strip())
+ try:
+ os.kill(pid, signal.SIGINT)
+ except OSError, v:
+ print v
+ os.remove(pid_file)
+ print name, 'stopped'
+ else:
+ print "Pid file %%s doesn't exist" %% pid_file
+ elif verb == 'restart':
+ main(['stop'])
+ main(['start'])
+ return
+ else:
+ raise ValueError("Unknown verb", verb)
+
+if __name__ == '__main__':
+ main()
+"""
Property changes on: zc.sshtunnel/trunk/src/zc/sshtunnel/recipe.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
Added: zc.sshtunnel/trunk/src/zc/sshtunnel/tests.py
===================================================================
--- zc.sshtunnel/trunk/src/zc/sshtunnel/tests.py 2007-02-26 16:45:47 UTC (rev 72823)
+++ zc.sshtunnel/trunk/src/zc/sshtunnel/tests.py 2007-02-26 17:15:19 UTC (rev 72824)
@@ -0,0 +1,43 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation 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.
+#
+##############################################################################
+"""\
+Test harness for zc.sshtunnel.
+
+"""
+__docformat__ = "reStructuredText"
+
+import unittest
+
+from zope.testing import doctest
+from zope.testing import renormalizing
+
+import zc.buildout.testing
+
+
+def setUp(test):
+ zc.buildout.testing.buildoutSetUp(test)
+ zc.buildout.testing.install_develop("zc.sshtunnel", test)
+ zc.buildout.testing.install("zope.testing", test)
+
+
+def test_suite():
+ return unittest.TestSuite([
+ doctest.DocFileSuite(
+ "README.txt",
+ setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
+ optionflags=doctest.ELLIPSIS,
+ checker=renormalizing.RENormalizing([
+ zc.buildout.testing.normalize_path])
+ ),
+ ])
Property changes on: zc.sshtunnel/trunk/src/zc/sshtunnel/tests.py
___________________________________________________________________
Name: svn:mime-type
+ text/x-python
Name: svn:eol-style
+ native
More information about the Checkins
mailing list