[Checkins] SVN: zc.zodbrecipes/branches/dev/ Initial implementation.

Jim Fulton jim at zope.com
Fri Apr 13 14:12:45 EDT 2007


Log message for revision 74121:
  Initial implementation.
  

Changed:
  _U  zc.zodbrecipes/branches/dev/
  A   zc.zodbrecipes/branches/dev/README.txt
  A   zc.zodbrecipes/branches/dev/buildout.cfg
  A   zc.zodbrecipes/branches/dev/setup.py
  A   zc.zodbrecipes/branches/dev/zc/
  A   zc.zodbrecipes/branches/dev/zc/__init__.py
  A   zc.zodbrecipes/branches/dev/zc/zodbrecipes/
  A   zc.zodbrecipes/branches/dev/zc/zodbrecipes/__init__.py
  A   zc.zodbrecipes/branches/dev/zc/zodbrecipes/tests.py
  A   zc.zodbrecipes/branches/dev/zc/zodbrecipes/zeo.txt

-=-

Property changes on: zc.zodbrecipes/branches/dev
___________________________________________________________________
Name: svn:ignore
   + doc.txt
bin
parts
develop-eggs


Added: zc.zodbrecipes/branches/dev/README.txt
===================================================================
--- zc.zodbrecipes/branches/dev/README.txt	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/README.txt	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,14 @@
+**************************************
+Zope3 Application and Instance Recipes
+**************************************
+
+Somewhat experimental recipes for creating Zope 3 instances with
+distinguishing features:
+
+- Don't use a skeletin
+
+- Seprates application and instance definition
+
+- Don't support package-includes
+
+.. contents::


Property changes on: zc.zodbrecipes/branches/dev/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/buildout.cfg
===================================================================
--- zc.zodbrecipes/branches/dev/buildout.cfg	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/buildout.cfg	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,24 @@
+[buildout]
+parts = test zodb server
+develop = .
+find-links = http://download.zope.org/distribution
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = zc.zodbrecipes
+
+[zodb]
+recipe = zc.recipe.egg:script
+eggs = ZODB3
+interpreter = py
+
+[server]
+recipe = zc.zodbrecipes:server
+zeo.conf =
+  <zeo>
+    address 8100
+  </zeo>
+  <filestorage 1>
+     path ${buildout:parts-directory}/Data.fs
+  </filestorage>
+     


Property changes on: zc.zodbrecipes/branches/dev/buildout.cfg
___________________________________________________________________
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/setup.py
===================================================================
--- zc.zodbrecipes/branches/dev/setup.py	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/setup.py	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,53 @@
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+long_description = (
+    read('README.txt')
+    + '\n' +
+    'Detailed Documentation\n'
+    '**********************\n'
+    + '\n' +
+    read('zc', 'zodbrecipes', 'zeo.txt')
+    + '\n' +
+    'Download\n'
+    '**********************\n'
+    )
+
+open('doc.txt', 'w').write(long_description)
+
+name = "zc.zodbrecipes"
+setup(
+    name = name,
+    version = "0.1",
+    author = "Jim Fulton",
+    author_email = "jim at zope.com",
+    description = "ZC Buildout recipes for ZODB",
+    license = "ZPL 2.1",
+    keywords = "zodb buildout",
+    url='http://svn.zope.org/'+name,
+    long_description=long_description,
+
+    packages = find_packages('.'),
+    include_package_data = True,
+    namespace_packages = ['zc'],
+    install_requires = ['zc.buildout', 'zope.testing', 'setuptools',
+                        'zc.recipe.egg', 'ZConfig', 'zdaemon', 'ZODB3'],
+    entry_points = {
+        'zc.buildout': [
+             'server = %s:StorageServer' % name,
+             ]
+        },
+##     extras_require = dict(
+##         tests = ['zdaemon', 'zc.recipe.filestorage'],
+##         ),
+    classifiers = [
+       'Framework :: Buildout',
+       'Intended Audience :: Developers',
+       'License :: OSI Approved :: Zope Public License',
+       'Topic :: Software Development :: Build Tools',
+       'Topic :: Software Development :: Libraries :: Python Modules',
+       ],
+    )


Property changes on: zc.zodbrecipes/branches/dev/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/zc/__init__.py
===================================================================
--- zc.zodbrecipes/branches/dev/zc/__init__.py	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/zc/__init__.py	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)


Property changes on: zc.zodbrecipes/branches/dev/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/zc/zodbrecipes/__init__.py
===================================================================
--- zc.zodbrecipes/branches/dev/zc/zodbrecipes/__init__.py	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/zc/zodbrecipes/__init__.py	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,332 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+
+import logging, os, shutil
+import zc.recipe.egg
+import zc.buildout
+import ZConfig.cfgparser
+import cStringIO
+
+logger = logging.getLogger('zc.zodbrecipes')
+
+class StorageServer:
+
+    def __init__(self, buildout, name, options):
+        self.name, self.options = name, options
+
+        deployment = self.deployment = options.get('deployment')
+        if deployment:
+            options['rc-directory'] = buildout[deployment]['rc-directory']
+            options['run-directory'] = buildout[deployment]['run-directory']
+            options['log-directory'] = buildout[deployment]['log-directory']
+            options['etc-directory'] = buildout[deployment]['etc-directory']
+            options['logrotate'] = os.path.join(
+                buildout[deployment]['logrotate-directory'],
+                deployment + '-' + name)
+            options['crontab-directory'] = buildout[
+                deployment]['crontab-directory']
+            options['user'] = buildout[deployment]['user']
+        else:
+            options['rc-directory'] = buildout['buildout']['bin-directory']
+            options['run-directory'] = os.path.join(
+                buildout['buildout']['parts-directory'],
+                self.name,
+                )
+
+        options['scripts'] = ''
+        options['eggs'] = options.get('eggs', 'zdaemon\nsetuptools')
+        self.egg = zc.recipe.egg.Egg(buildout, name, options)
+
+        options['runzeo'] = os.path.join(
+            buildout['buildout']['bin-directory'],
+            options.get('runzeo', 'runzeo'),
+            )
+        options['zeopack'] = os.path.join(
+            buildout['buildout']['bin-directory'],
+            options.get('zeopack', 'zeopack'),
+            )
+
+    def install(self):
+        options = self.options
+
+        if not os.path.exists(options['runzeo']):
+            logger.warn(no_runzeo % options['runzeo'])
+
+        run_directory = options['run-directory']
+        deployment = self.deployment
+        if deployment:
+            zeo_conf_path = os.path.join(options['etc-directory'],
+                                         self.name+'-zeo.conf')
+            zdaemon_conf_path = os.path.join(options['etc-directory'],
+                                             self.name+'-zdaemon.conf')
+            event_log_path = os.path.join(options['log-directory'],
+                                          self.name+'-zeo.log')
+            socket_path = os.path.join(run_directory,
+                                       self.name+'-zdaemon.sock')
+            rc = deployment + '-' + self.name
+
+            logrotate = options['logrotate']
+            open(logrotate, 'w').write(logrotate_template % dict(
+                logfile=event_log_path,
+                rc=rc,
+                ))
+            
+            creating = [zeo_conf_path, zdaemon_conf_path, logrotate,
+                        os.path.join(options['rc-directory'], rc),
+                        ]
+
+            pack = options.get('pack')
+            if pack:
+                pack = pack.split()
+                if len(pack) < 5:
+                    raise zc.buildout.UserError(
+                        'Too few crontab fields in pack specification')
+                if len(pack) > 6:
+                    raise zc.buildout.UserError(
+                        'Too many values in pack option')
+                pack_path = os.path.join(
+                    options['crontab-directory'],
+                    "pack-%s-%s" % (deployment, self.name),
+                    )
+                if not os.path.exists(options['zeopack']):
+                    logger.warn("Couln'e find zeopack script, %r",
+                                options['zeopack'])
+        else:
+            zeo_conf_path = os.path.join(run_directory, 'zeo.conf')
+            zdaemon_conf_path = os.path.join(run_directory, 'zdaemon.conf')
+            event_log_path = os.path.join(run_directory, 'zeo.log')
+            socket_path = os.path.join(run_directory, 'zdaemon.sock')
+            rc = self.name
+            creating = [run_directory,
+                        os.path.join(options['rc-directory'], rc),
+                        ]
+            if not os.path.exists(run_directory):
+                os.mkdir(run_directory)
+            pack = pack_path = None
+
+        try:
+            zeo_conf = options.get('zeo.conf', '')+'\n'
+            zeo_conf = ZConfigParse(cStringIO.StringIO(zeo_conf))
+
+            zeo_section = [s for s in zeo_conf.sections if s.type == 'zeo']
+            if not zeo_section:
+                raise zc.buildout.UserError('No zeo section was defined.')
+            if len(zeo_section) > 1:
+                raise zc.buildout.UserError('Too many zeo sections.')
+            zeo_section = zeo_section[0]
+            if not 'address' in zeo_section:
+                raise zc.buildout.UserError('No ZEO address was specified.')
+
+            storages = [s.name for s in zeo_conf.sections
+                        if s.type not in ('zeo', 'eventlog', 'runner')
+                        ]
+
+            if not storages:
+                raise zc.buildout.UserError('No storages were defined.')
+
+            if not [s for s in zeo_conf.sections if s.type == 'eventlog']:
+                zeo_conf.sections.append(event_log('STDOUT'))
+
+            zdaemon_conf = options.get('zdaemon.conf', '')+'\n'
+            zdaemon_conf = ZConfigParse(cStringIO.StringIO(zdaemon_conf))
+
+            defaults = {
+                'program': "%s -C %s" % (options['runzeo'], zeo_conf_path),
+                'daemon': 'on',
+                'transcript': event_log_path,
+                'socket-name': socket_path,
+                'directory' : run_directory,
+                }
+            if deployment:
+                defaults['user'] = options['user']
+            runner = [s for s in zdaemon_conf.sections
+                      if s.type == 'runner']
+            if runner:
+                runner = runner[0]
+            else:
+                runner = ZConfigSection('runner')
+                zdaemon_conf.sections.insert(0, runner)
+            for name, value in defaults.items():
+                if name not in runner:
+                    runner[name] = value
+
+            if not [s for s in zdaemon_conf.sections
+                    if s.type == 'eventlog']:
+                zdaemon_conf.sections.append(event_log(event_log_path))
+
+            zdaemon_conf = str(zdaemon_conf)
+
+            self.egg.install()
+            requirements, ws = self.egg.working_set()
+
+            open(zeo_conf_path, 'w').write(str(zeo_conf))
+            open(zdaemon_conf_path, 'w').write(str(zdaemon_conf))
+
+            self.egg.install()
+            requirements, ws = self.egg.working_set()
+
+            zc.buildout.easy_install.scripts(
+                [(rc, 'zdaemon.zdctl', 'main')],
+                ws, options['executable'], options['rc-directory'],
+                arguments = ('['
+                             '\n        %r, %r,'
+                             '\n        ]+sys.argv[1:]'
+                             '\n        '
+                             % ('-C', zdaemon_conf_path,
+                                )
+                             ),
+                )
+
+            if pack:
+                address = zeo_section['address']
+                if ':' in address:
+                    host, port = address.split(':')
+                    address = '-h %s -p %s' % (host, port)
+                else:
+                    try:
+                        port = int(address)
+                    except:
+                        address = '-U '+address
+                    else:
+                        address = '-p '+address
+                f = open(pack_path, 'w')
+                if len(pack) == 6:
+                    days = pack[5]
+                    pack = pack[:5]
+                else:
+                    days = 1
+                for storage in storages:
+                    f.write("%s %s %s -S %s -d %s\n" % (
+                            ' '.join(pack),
+                            options['zeopack'],
+                            address, storage, days))
+                f.close()
+
+            return creating
+
+        except:
+            for f in creating:
+                if os.path.isdir(f):
+                    shutil.rmtree(f)
+                elif os.path.exists(f):
+                    os.remove(f)
+            raise
+
+
+    update = install
+
+no_runzeo = """
+A runzeo script couldn't be found at:
+
+  %r
+
+You may need to generate a runzeo script using the
+zc.recipe.eggs:script recipe and the ZODB3 egg, or you may need
+to specify the location of a script using the runzeo option.
+"""
+
+
+def event_log(path, *data):
+    return ZConfigSection(
+        'eventlog', '', None,
+        [ZConfigSection('logfile', '',
+                        dict(path=path)
+                        )
+         ],
+        )
+
+event_log_template = """
+<eventlog>
+  <logfile>
+    path %s
+    formatter zope.exceptions.log.Formatter
+  </logfile>
+</eventlog>
+"""
+
+logrotate_template = """%(logfile)s {
+  rotate 5
+  weekly
+  postrotate
+    %(rc)s reopen_transcript
+  endscript
+}
+"""
+
+
+class ZConfigResource:
+
+    def __init__(self, file, url=''):
+        self.file, self.url = file, url
+
+class ZConfigSection(dict):
+
+    def __init__(self, type='', name='', data=None, sections=None):
+        dict.__init__(self)
+        if data:
+            self.update(data)
+        self.sections = sections or []
+        self.type, self.name = type, name
+
+    def addValue(self, key, value, *args):
+        self[key] = value
+
+    def __str__(self, pre=''):
+        result = []
+        if self.type:
+            if self.name:
+                result = ['%s<%s %s>' % (pre, self.type, self.name)]
+            else:
+                result = ['%s<%s>' % (pre, self.type)]
+            pre += '  '
+
+        for name, value in sorted(self.items()):
+            result.append('%s%s %s' % (pre, name, value))
+
+        if self.sections and self:
+            result.append('')
+
+        for section in self.sections:
+            result.append(section.__str__(pre))
+        
+        if self.type:
+            result.append('%s</%s>' % (pre[:-2], self.type))
+            result.append('')
+                          
+        return '\n'.join(result).rstrip()+'\n'
+  
+class ZConfigContext:
+
+    def __init__(self):
+        self.top = ZConfigSection()
+        self.sections = []
+
+    def startSection(self, container, type, name):
+        newsec = ZConfigSection(type, name)
+        container.sections.append(newsec)
+        return newsec
+
+    def endSection(self, container, type, name, newsect):
+        pass
+
+    def importSchemaComponent(self, pkgname):
+        pass
+
+    def includeConfiguration(self, section, newurl, defines):
+        raise NotImplementedError('includes are not supported')
+
+def ZConfigParse(file):
+    c = ZConfigContext()
+    ZConfig.cfgparser.ZConfigParser(ZConfigResource(file), c).parse(c.top)
+    return c.top


Property changes on: zc.zodbrecipes/branches/dev/zc/zodbrecipes/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/zc/zodbrecipes/tests.py
===================================================================
--- zc.zodbrecipes/branches/dev/zc/zodbrecipes/tests.py	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/zc/zodbrecipes/tests.py	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+
+import os, re, shutil, sys, tempfile
+import pkg_resources
+
+import zc.buildout.testing
+
+import unittest
+import zope.testing
+from zope.testing import doctest, renormalizing
+
+
+def setUp(test):
+    zc.buildout.testing.buildoutSetUp(test)
+    zc.buildout.testing.install_develop('zc.zodbrecipes', test)
+    zc.buildout.testing.install('zope.testing', test)
+    zc.buildout.testing.install('zc.recipe.egg', test)
+    zc.buildout.testing.install('zdaemon', test)
+    zc.buildout.testing.install('ZConfig', test)
+    zc.buildout.testing.install('ZODB3', test)
+    zc.buildout.testing.install('zope.proxy', test)
+    zc.buildout.testing.install('zope.interface', test)
+
+
+checker = renormalizing.RENormalizing([
+    zc.buildout.testing.normalize_path,
+    (re.compile(
+    "Couldn't find index page for '[a-zA-Z0-9.]+' "
+    "\(maybe misspelled\?\)"
+    "\n"
+    ), ''),
+    (re.compile('#![^\n]+\n'), ''),                
+    (re.compile('-\S+-py\d[.]\d(-\S+)?.egg'),
+     '-pyN.N.egg',
+    ),
+    ])
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite(
+            'zeo.txt',
+            setUp=setUp, tearDown=zc.buildout.testing.buildoutTearDown,
+            checker=checker,
+            ),
+        
+        ))
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')


Property changes on: zc.zodbrecipes/branches/dev/zc/zodbrecipes/tests.py
___________________________________________________________________
Name: svn:keywords
   + Id
Name: svn:eol-style
   + native

Added: zc.zodbrecipes/branches/dev/zc/zodbrecipes/zeo.txt
===================================================================
--- zc.zodbrecipes/branches/dev/zc/zodbrecipes/zeo.txt	2007-04-13 17:14:09 UTC (rev 74120)
+++ zc.zodbrecipes/branches/dev/zc/zodbrecipes/zeo.txt	2007-04-13 18:12:45 UTC (rev 74121)
@@ -0,0 +1,413 @@
+Defining ZEO Storage Servers
+============================
+
+The zc.zodbrecipes:server recipe can be used to define ZEO storage
+servers. To define a storage server, you define a part for the server
+and specify configuration data.  
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = server
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ... ''')
+
+Here we specified a minimal configuration using a file-storage.  When
+we run the buildout:
+
+    >>> print system(buildout),
+    buildout: Installing server
+    zc.zodbrecipes: 
+    A runzeo script couldn't be found at:
+    <BLANKLINE>
+      '/sample-buildout/bin/runzeo'
+    <BLANKLINE>
+    You may need to generate a runzeo script using the
+    zc.recipe.eggs:script recipe and the ZODB3 egg, or you may need
+    to specify the location of a script using the runzeo option.
+    <BLANKLINE>
+
+We got a warning because the recipe expects there to be a runzeo
+script and we haven't created one.  This is done using the
+zc.recipe.egg:script recipe:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = zodb server
+    ... 
+    ... [zodb]
+    ... recipe = zc.recipe.egg:script
+    ... eggs = ZODB3
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ... ''')
+
+    >>> print system(buildout),
+    buildout: Installing zodb
+    buildout: Updating server
+
+We get 2 things.  We get a directory in parts containing ZEO and
+zdaemon configuration files:
+
+    >>> ls('parts', 'server')
+    -  zdaemon.conf
+    -  zeo.conf
+
+Let's look at the configuration files:
+
+    >>> cat('parts', 'server', 'zeo.conf')
+    <zeo>
+      address 8100
+      monitor-address 8101
+      transaction-timeout 300
+    </zeo>
+    <BLANKLINE>
+    <filestorage main>
+      path /databases/Data.fs
+    </filestorage>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path STDOUT
+      </logfile>
+    <BLANKLINE>
+    </eventlog>
+
+We see the same data we input with the addition of an eventlog section
+that directs logging to standard out.  In production, we'll use
+zdaemon's transacript log to capture this logging output in a file.
+If we wish, we can specify a log file ourselves:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = zodb server
+    ... 
+    ... [zodb]
+    ... recipe = zc.recipe.egg:script
+    ... eggs = ZODB3
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ...    <eventlog>
+    ...      <logfile>
+    ...        path /var/log/zeo.log
+    ...      </logfile>
+    ...    </eventlog>
+    ... ''')
+
+    >>> print system(buildout),
+    buildout: Uninstalling server
+    buildout: Updating zodb
+    buildout: Installing server
+
+    >>> cat('parts', 'server', 'zeo.conf')
+    <zeo>
+      address 8100
+      monitor-address 8101
+      transaction-timeout 300
+    </zeo>
+    <BLANKLINE>
+    <filestorage main>
+      path /databases/Data.fs
+    </filestorage>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /var/log/zeo.log
+      </logfile>
+    <BLANKLINE>
+    </eventlog>
+
+But we'll stick with the default:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = zodb server
+    ... 
+    ... [zodb]
+    ... recipe = zc.recipe.egg:script
+    ... eggs = ZODB3
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ... ''')
+
+    >>> print system(buildout),
+    buildout: Uninstalling server
+    buildout: Updating zodb
+    buildout: Installing server
+
+Let's look at the zdaemon log file:
+
+    >>> cat('parts', 'server', 'zdaemon.conf')
+    <runner>
+      daemon on
+      directory /sample-buildout/parts/server
+      program /sample-buildout/bin/runzeo -C /sample-buildout/parts/server/zeo.conf
+      socket-name /sample-buildout/parts/server/zdaemon.sock
+      transcript /sample-buildout/parts/server/zeo.log
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /sample-buildout/parts/server/zeo.log
+      </logfile>
+    <BLANKLINE>
+    </eventlog>
+
+We run the runzeo script with the zeo.conf file.  Log and run-time
+files are places in the server part directory.  We use a transcript
+log to provide the ZEO server log.  I like to use the transacriot log
+because it captures program output, such as start-up exceptions that
+aren't captured in a program's logs.
+
+And we get a control script generated in our bin directory:
+
+    >>> cat('bin', 'server')
+    #!/usr/local/bin/python2.4
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/sample-buildout/eggs/zdaemon-2.0-py2.4.egg',
+      '/sample-buildout/eggs/setuptools-0.6-py2.4.egg',
+      '/sample-buildout/eggs/ZConfig-2.4-py2.4.egg',
+      ]
+    <BLANKLINE>
+    import zdaemon.zdctl
+    <BLANKLINE>
+    if __name__ == '__main__':
+        zdaemon.zdctl.main([
+            '-C', '/sample-buildout/parts/server/zdaemon.conf',
+            ]+sys.argv[1:]
+            )
+
+This is a zdaemon script.  We can use this to control the ZEO server
+process.
+
+Unix Deployment support
+=======================
+
+The server recipe works with the zc.recipe.deployment.  In particular,
+if a deployment option is specified, it names a part or section that
+defines the following uptions:
+
+crontab-directory
+  A directory for crontab files.
+
+etc-directory
+  A directory for configuration files.
+
+log-directory
+  A directory for log files.
+
+logrotate-directory
+  A directory for logrotate configuration files.
+
+rc-directory
+  A directory for run-control scripts.
+
+run-directory
+  A directory for run-time files.
+
+user
+  The user the server process should run as
+
+Let's create some directories and add a deployment section to our
+buildout:
+
+    >>> for d in 'cron', 'etc', 'log', 'rotate', 'rc', 'run':
+    ...     mkdir(d)
+    ...     globals()[d] = join(sample_buildout, d)
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = zodb server
+    ... 
+    ... [zodb]
+    ... recipe = zc.recipe.egg:script
+    ... eggs = ZODB3
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ... deployment = demo
+    ...
+    ... [demo]
+    ... crontab-directory = %(cron)s
+    ... etc-directory = %(etc)s
+    ... log-directory = %(log)s
+    ... logrotate-directory = %(rotate)s
+    ... rc-directory = %(rc)s
+    ... run-directory = %(run)s
+    ... user = bob
+    ... ''' % globals())
+
+    >>> print system(buildout),
+    buildout: Uninstalling server
+    buildout: Updating zodb
+    buildout: Installing server
+
+Now, the parts directory and the control script will be gone:
+
+    >>> import os
+    >>> os.path.exists(join('parts', 'server'))
+    False
+    >>> os.path.exists(join('bin', 'server'))
+    False
+
+Instead, the control script will be in the rc directory:
+
+    >>> ls('rc')
+    -  demo-server
+
+The run-control script name now combines the deployment name and the
+script name.
+
+and the configuration files will be in the etc directory:
+
+    >>> ls('etc')
+    -  server-zdaemon.conf
+    -  server-zeo.conf
+
+In additional we'll get a logrotate configuration file:
+
+    >>> cat('rotate', 'demo-server')
+    /sample-buildout/log/server-zeo.log {
+      rotate 5
+      weekly
+      postrotate
+        demo-server reopen_transcript
+      endscript
+    }
+
+This will rotate the zeo log file once a week.
+
+If we look at the zdaemon configuration file, we can see that it reflects
+the deployment locations:
+
+    >>> cat('etc', 'server-zdaemon.conf')
+    <runner>
+      daemon on
+      directory /sample-buildout/run
+      program /sample-buildout/bin/runzeo -C /sample-buildout/etc/server-zeo.conf
+      socket-name /sample-buildout/run/server-zdaemon.sock
+      transcript /sample-buildout/log/server-zeo.log
+      user bob
+    </runner>
+    <BLANKLINE>
+    <eventlog>
+      <logfile>
+        path /sample-buildout/log/server-zeo.log
+      </logfile>
+    <BLANKLINE>
+    </eventlog>
+
+Note that different file names are used.  Since a deployment may be
+(and usually is) shared by multiple parts, files are prefixed with
+their part names.  Also note that the deployment user is set in the
+zdaemon configuration.
+
+We can request definition of a cron job to pack the databases by
+specifying a pack option.  This option takes 5 or 6 values.  The
+first 5 values are the time and date fields defined by Unix crontab
+files. The last field is the number of days in the past to pack to and
+defaults to 1.
+
+Let's add a pack option:
+
+    >>> write('buildout.cfg',
+    ... '''
+    ... [buildout]
+    ... parts = zodb server
+    ... 
+    ... [zodb]
+    ... recipe = zc.recipe.egg:script
+    ... eggs = ZODB3
+    ... 
+    ... [server]
+    ... recipe = zc.zodbrecipes:server
+    ... zeo.conf = 
+    ...    <zeo>
+    ...       address 8100
+    ...       monitor-address 8101
+    ...       transaction-timeout 300
+    ...    </zeo>
+    ...    <filestorage main>
+    ...       path /databases/Data.fs
+    ...    </filestorage>
+    ... deployment = demo
+    ... pack = 1 1 * * 0 3
+    ...
+    ... [demo]
+    ... crontab-directory = %(cron)s
+    ... etc-directory = %(etc)s
+    ... log-directory = %(log)s
+    ... logrotate-directory = %(rotate)s
+    ... rc-directory = %(rc)s
+    ... run-directory = %(run)s
+    ... user = bob
+    ... ''' % globals())
+
+    >>> print system(buildout+' -D'),
+    buildout: Uninstalling server
+    buildout: Updating zodb
+    buildout: Installing server
+
+Now, we'll get a crontab file:
+
+    >>> cat(cron, 'pack-demo-server')
+    1 1 * * 0 /sample-buildout/bin/zeopack -p 8100 -S main -d 3
+
+In this example, we'll pack the databases every Sunday at 1:01 to 3
+days.


Property changes on: zc.zodbrecipes/branches/dev/zc/zodbrecipes/zeo.txt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list