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