From 3ec22f0bf0e47f72496227b0fd0a7a070c4b2211 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C5=81ukasz=20Nowak?= <luke@nexedi.com>
Date: Wed, 19 Oct 2011 14:39:59 +0200
Subject: [PATCH] Checkpoint: Zope is configured.

---
 setup.py                                      |   1 +
 .../generic_zope_zeo_client/__init__.py       | 147 ++++++++++++++++++
 .../template/site.zcml                        |  26 ++++
 .../template/zope.conf.in                     |  68 ++++++++
 .../template/zope.zeo.entry.conf.in           |  10 ++
 software/erp5/snippet-zope.cfg                |   4 +-
 software/erp5/software.cfg                    |   2 +-
 7 files changed, 255 insertions(+), 3 deletions(-)
 create mode 100644 slapos/recipe/generic_zope_zeo_client/__init__.py
 create mode 100644 slapos/recipe/generic_zope_zeo_client/template/site.zcml
 create mode 100644 slapos/recipe/generic_zope_zeo_client/template/zope.conf.in
 create mode 100644 slapos/recipe/generic_zope_zeo_client/template/zope.zeo.entry.conf.in

diff --git a/setup.py b/setup.py
index 01424546e..4f774b764 100644
--- a/setup.py
+++ b/setup.py
@@ -85,6 +85,7 @@ setup(name=name,
           'xwiki = slapos.recipe.xwiki:Recipe',
           'zabbixagent = slapos.recipe.zabbixagent:Recipe',
           'generic.zope = slapos.recipe.generic_zope:Recipe',
+          'generic.zope.zeo.client = slapos.recipe.generic_zope_zeo_client:Recipe',
           'generate.erp5.tidstorage = slapos.recipe.generate_erp5_tidstorage:Recipe',
           'zeo = slapos.recipe.zeo:Recipe',
       ]},
diff --git a/slapos/recipe/generic_zope_zeo_client/__init__.py b/slapos/recipe/generic_zope_zeo_client/__init__.py
new file mode 100644
index 000000000..3318935e6
--- /dev/null
+++ b/slapos/recipe/generic_zope_zeo_client/__init__.py
@@ -0,0 +1,147 @@
+##############################################################################
+#
+# Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsibility of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# guarantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 3
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+from slapos.recipe.librecipe import GenericBaseRecipe
+import binascii
+import hashlib
+import os
+import re
+import zc.buildout
+
+_isurl = re.compile('([a-zA-Z0-9+.-]+)://').match
+
+# based on Zope2.utilities.mkzopeinstance.write_inituser
+def Zope2InitUser(path, username, password):
+  open(path, 'w').write('')
+  os.chmod(path, 0600)
+  open(path, "w").write('%s:{SHA}%s\n' % (
+    username,binascii.b2a_base64(hashlib.sha1(password).digest())[:-1]))
+
+class Recipe(GenericBaseRecipe):
+  def _options(self, options):
+    options['password'] = self.generatePassword()
+    options['deadlock-password'] = self.generatePassword()
+
+  def install(self):
+    """
+    All zope have to share file created by portal_classes
+    (until everything is integrated into the ZODB).
+    So, do not request zope instance and create multiple in the same partition.
+    """
+    path_list = []
+    Zope2InitUser(self.options['inituser'], self.options['user'],
+      self.options['password'])
+
+    # Symlink to BT5 repositories defined in instance config.
+    # Those paths will eventually end up in the ZODB, and having symlinks
+    # inside the XXX makes it possible to reuse such ZODB with another software
+    # release[ version].
+    # Note: this path cannot be used for development, it's really just a
+    # read-only repository.
+    repository_path = self.options['bt5-repository']
+
+    self.bt5_repository_list = []
+    append = self.bt5_repository_list.append
+    for repository in self.options.get('bt5-repository-list', '').split():
+      repository = repository.strip()
+      if not repository:
+        continue
+
+      if _isurl(repository) and not repository.startswith("file://"):
+        # XXX: assume it's a valid URL
+        append(repository)
+        continue
+
+      if repository.startswith('file://'):
+        repository = repository.replace('file://', '', '')
+
+      if os.path.isabs(repository):
+        repo_id = hashlib.sha1(repository).hexdigest()
+        link = os.path.join(repository_path, repo_id)
+        if os.path.lexists(link):
+          if not os.path.islink(link):
+            raise zc.buildout.UserError(
+              'Target link already %r exists but it is not link' % link)
+          os.unlink(link)
+        os.symlink(repository, link)
+        self.logger.debug('Created link %r -> %r' % (link, repository_path))
+        # Always provide a URL-Type
+        append("file://" + link)
+
+    # Generate Zeo connections
+    zeo_snippet_template = open(self.getTemplateFilename('zope.zeo.entry.conf.in'
+      )).read()
+    zeo_snippet_list = []
+    for zeo_line in self.options['zeo-connection-string'].splitlines():
+      zeo_line.strip()
+      if not zeo_line:
+        continue
+      d = dict()
+      for param in zeo_line.split():
+        k, v = param.split('=')
+        d[k.strip()] = v.strip()
+      zeo_snippet_list.append(zeo_snippet_template % d)
+    # Create zope configuration file
+    zope_config = dict(
+        products=self.options['products'],
+        thread_amount=self.options['thread-amount'],
+        zodb_configuration='\n'.join(zeo_snippet_list)
+    )
+    zope_environment = dict(
+      TMP=self.options['tmp-path'],
+      TMPDIR=self.options['tmp-path'],
+      HOME=self.options['tmp-path'],
+      PATH=self.options['bin-path']
+    )
+    # configure default Zope2 zcml
+    open(self.options['site-zcml'], 'w').write(open(self.getTemplateFilename(
+        'site.zcml')).read())
+    zope_config['instance'] = self.options['instance-path']
+    zope_config['event_log'] = self.options['event-log']
+    zope_config['z2_log'] = self.options['z2-log']
+    zope_config['pid-filename'] = self.options['pid-file']
+    zope_config['lock-filename'] = self.options['lock-file']
+    prefixed_products = []
+    for product in reversed(zope_config['products'].split()):
+      product = product.strip()
+      if product:
+        prefixed_products.append('products %s' % product)
+    prefixed_products.insert(0, 'products %s' % self.options[
+      'instance-products'])
+    zope_config['products'] = '\n'.join(prefixed_products)
+    zope_config['address'] = '%s:%s' % (self.options['ip'], self.options['port'])
+    zope_config.update(dump_url=self.options['deadlock-path'],
+      secret=self.options['deadlock-password'])
+
+    zope_wrapper_template_location = self.getTemplateFilename('zope.conf.in')
+    zope_conf_content = self.substituteTemplate(zope_wrapper_template_location,
+      zope_config)
+
+    zope_conf_path = self.createFile(self.options['configuration-file'], zope_conf_content)
+    path_list.append(zope_conf_path)
+    # Create init script
+    path_list.append(self.createPythonScript(self.options['wrapper'], 'slapos.recipe.librecipe.execute.executee', [[self.options['runzope-binary'].strip(), '-C', zope_conf_path], zope_environment]))
+    return path_list
diff --git a/slapos/recipe/generic_zope_zeo_client/template/site.zcml b/slapos/recipe/generic_zope_zeo_client/template/site.zcml
new file mode 100644
index 000000000..47454428e
--- /dev/null
+++ b/slapos/recipe/generic_zope_zeo_client/template/site.zcml
@@ -0,0 +1,26 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:meta="http://namespaces.zope.org/meta"
+    xmlns:five="http://namespaces.zope.org/five">
+
+  <include package="Products.Five" />
+  <meta:redefinePermission from="zope2.Public" to="zope.Public" />
+
+
+  <!-- Load the meta -->
+  <include files="package-includes/*-meta.zcml" />
+  <five:loadProducts file="meta.zcml"/>
+
+  <!-- Load the configuration -->
+  <include files="package-includes/*-configure.zcml" />
+  <five:loadProducts />
+
+  <!-- Load the configuration overrides-->
+  <includeOverrides files="package-includes/*-overrides.zcml" />
+  <five:loadProductsOverrides />
+
+
+  <securityPolicy
+      component="Products.Five.security.FiveSecurityPolicy" />
+
+</configure>
diff --git a/slapos/recipe/generic_zope_zeo_client/template/zope.conf.in b/slapos/recipe/generic_zope_zeo_client/template/zope.conf.in
new file mode 100644
index 000000000..c705ce276
--- /dev/null
+++ b/slapos/recipe/generic_zope_zeo_client/template/zope.conf.in
@@ -0,0 +1,68 @@
+## Zope 2 configuration file generated by SlapOS
+
+# Some defines
+%%define INSTANCE %(instance)s
+instancehome $INSTANCE
+
+# Used products
+%(products)s
+
+# Environment is setup in running wrapper script
+# Reason: zope.conf is read too late for some componets
+
+# No need to debug
+debug-mode off
+
+# One thread is safe enough
+zserver-threads %(thread_amount)s
+
+# File location
+pid-filename %(pid-filename)s
+lock-filename %(lock-filename)s
+
+# Temporary storage database (for sessions)
+<zodb_db temporary>
+     <temporarystorage>
+       name temporary storage for sessioning
+     </temporarystorage>
+     mount-point /temp_folder
+     container-class Products.TemporaryFolder.TemporaryContainer
+</zodb_db>
+
+# Logging configuration
+<eventlog>
+  <logfile>
+    dateformat
+    path %(event_log)s
+  </logfile>
+</eventlog>
+<logger access>
+  <logfile>
+    dateformat
+    path %(z2_log)s
+  </logfile>
+</logger>
+
+# Serving configuration
+<http-server>
+  address %(address)s
+</http-server>
+
+# ZODB configuration
+%(zodb_configuration)s
+
+<zoperunner>
+    program $INSTANCE/bin/runzope
+</zoperunner>
+
+# DeadlockDebugger configuration
+<product-config DeadlockDebugger>
+  dump_url %(dump_url)s
+  secret %(secret)s
+</product-config>
+
+# ERP5 Timer Service
+%%import timerserver
+<timer-server>
+  interval 5
+</timer-server>
diff --git a/slapos/recipe/generic_zope_zeo_client/template/zope.zeo.entry.conf.in b/slapos/recipe/generic_zope_zeo_client/template/zope.zeo.entry.conf.in
new file mode 100644
index 000000000..3ef43f262
--- /dev/null
+++ b/slapos/recipe/generic_zope_zeo_client/template/zope.zeo.entry.conf.in
@@ -0,0 +1,10 @@
+<zodb_db %(storage-name)s>
+  cache-size %(zope-cache-size)s
+  mount-point %(mount-point)s
+  <zeoclient>
+    cache-size %(zeo-cache-size)s
+    server %(server)s
+    storage %(storage-name)s
+    name %(storage-name)s
+  </zeoclient>
+</zodb_db>
diff --git a/software/erp5/snippet-zope.cfg b/software/erp5/snippet-zope.cfg
index 4350e879e..9286736cf 100644
--- a/software/erp5/snippet-zope.cfg
+++ b/software/erp5/snippet-zope.cfg
@@ -1,5 +1,5 @@
 [%(zope_id)s]
-recipe = slapos.cookbook:generic.zope
+recipe = slapos.cookbook:generic.zope.zeo.client
 
 # XXX: products won't be needed as soon as all ERP5 (and products-deps)
 # products will be eggified so then it will be possible to use them thanks to
@@ -13,7 +13,7 @@ ip = $${slap-network-information:local-ipv4}
 thread-amount = %(zope_thread_amount)s
 deadlock-path = /manage_debug_threads
 timezone = %(timezone)s
-zeo_connection_string =
+zeo-connection-string =
   %(zeo_connection_string)s
 
 # Paths
diff --git a/software/erp5/software.cfg b/software/erp5/software.cfg
index a67175665..44c5484b8 100644
--- a/software/erp5/software.cfg
+++ b/software/erp5/software.cfg
@@ -95,7 +95,7 @@ mode = 0644
 [template-snippet-zope]
 recipe = slapos.recipe.template
 url = ${:_profile_base_location_}/snippet-zope.cfg
-md5sum = 7ba22f125ffe67a3134631aef71a74f4
+md5sum = 559e53e669d7255f11527ed47ae0b244
 output = ${buildout:directory}/template-snippet-zope.cfg
 mode = 0644
 
-- 
2.30.9