Commit 88976343 authored by Alain Takoudjou's avatar Alain Takoudjou

Merge branch 'master' into 1.0

parents b6e38ca4 596225bb
...@@ -8,7 +8,7 @@ extends = ...@@ -8,7 +8,7 @@ extends =
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = ftp://ftp.cyrusimap.org/cyrus-sasl/cyrus-sasl-2.1.26.tar.gz url = ftp://ftp.cyrusimap.org/cyrus-sasl/cyrus-sasl-2.1.26.tar.gz
md5sum = a7f4e5e559a0e37b3ffc438c9456e425 md5sum = a7f4e5e559a0e37b3ffc438c9456e425
location = ${buildout:parts-directory}/${:_buildout_section_name_}
configure-options = configure-options =
--disable-digest --disable-digest
--disable-gssapi --disable-gssapi
...@@ -18,6 +18,7 @@ configure-options = ...@@ -18,6 +18,7 @@ configure-options =
--without-openssl --without-openssl
--without-pam --without-pam
--without-saslauthd --without-saslauthd
--with-plugindir=${:location}/lib/sasl2
# it seems that parallel build sometimes fails. # it seems that parallel build sometimes fails.
make-options = make-options =
-j1 -j1
......
...@@ -6,14 +6,39 @@ extends = ...@@ -6,14 +6,39 @@ extends =
../libdb/buildout.cfg ../libdb/buildout.cfg
../openssl/buildout.cfg ../openssl/buildout.cfg
../pcre/buildout.cfg ../pcre/buildout.cfg
../cyrus-sasl/buildout.cfg
parts = postfix [noroot.patch]
recipe = hexagonit.recipe.download
url =${:_profile_base_location_}/${:filename}
filename = ${:_buildout_section_name_}
download-only = true
md5sum = 738bcc97b8044c45b58708bdf3a84b8e
[skip-libdb-check.patch]
recipe = hexagonit.recipe.download
url =${:_profile_base_location_}/${:filename}
filename = ${:_buildout_section_name_}
download-only = true
md5sum = f7fdbd8787874b535fee548b0139c0d8
[postfix-linux4.patch]
recipe = hexagonit.recipe.download
url = ${:_profile_base_location_}/${:filename}
filename = ${:_buildout_section_name_}
download-only = true
md5sum = 2549e80b9834c58185a18bfbf55c2767
[postfix] [postfix]
recipe = slapos.recipe.cmmi recipe = slapos.recipe.cmmi
url = ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-2.8.3.tar.gz url = ftp://ftp.porcupine.org/mirrors/postfix-release/official/postfix-2.11.1.tar.gz
md5sum = b3922ededd3fd6051f759e58a4ada3ae md5sum = 56ac1f1a79737c4ac1e24535a122a4a6
location = ${buildout:parts-directory}/${:_buildout_section_name_} location = ${buildout:parts-directory}/${:_buildout_section_name_}
patch-options = -p1
patches =
${noroot.patch:location}/${noroot.patch:filename}
${skip-libdb-check.patch:location}/${skip-libdb-check.patch:filename}
${postfix-linux4.patch:location}/${postfix-linux4.patch:filename}
configure-command = make configure-command = make
configure-options = makefiles CCARGS='-DUSE_TLS -DHAS_PCRE -DHAS_DB -I${libdb:location}/include -I${pcre:location}/include -I${openssl:location}/include' AUXLIBS='-L${openssl:location}/lib -L${pcre:location}/lib -L${libdb:location}/lib -lssl -lpcre -ldb -lcrypto -Wl,-rpath=${openssl:location}/lib -Wl,-rpath=${pcre:location}/lib -Wl,-rpath=${libdb:location}/lib' configure-options = makefiles CCARGS='-DUSE_SASL_AUTH -DUSE_CYRUS_SASL -DUSE_TLS -DHAS_PCRE -DHAS_DB -I${libdb:location}/include -I${pcre:location}/include -I${openssl:location}/include -I${cyrus-sasl:location}/include/sasl' AUXLIBS='-L${openssl:location}/lib -L${pcre:location}/lib -L${libdb:location}/lib -L${cyrus-sasl:location}/lib -lssl -lpcre -ldb -lcrypto -lsasl2 -Wl,-rpath=${openssl:location}/lib -Wl,-rpath=${pcre:location}/lib -Wl,-rpath=${libdb:location}/lib -Wl,-rpath=${cyrus-sasl:location}/lib'
make-targets = non-interactive-package install_root=${:location} make-targets = non-interactive-package install_root=${:location}
diff --git a/src/global/mail_params.c b/src/global/mail_params.c
index 2d91977..0f06298 100644
--- a/src/global/mail_params.c
+++ b/src/global/mail_params.c
@@ -721,7 +721,9 @@ void mail_params_init()
check_default_privs();
check_mail_owner();
check_sgid_group();
+ /*
check_overlap();
+ */
#ifdef HAS_DB
dict_db_cache_size = var_db_read_buf;
#endif
diff --git a/src/master/master.c b/src/master/master.c
index a9d5d1b..db88c55 100644
--- a/src/master/master.c
+++ b/src/master/master.c
@@ -315,10 +315,10 @@ int main(int argc, char **argv)
* privileges for selected operations. That's right - it takes privileges
* to toss privileges.
*/
- if (getuid() != 0)
+ /*if (getuid() != 0)
msg_fatal("the master command is reserved for the superuser");
if (unsafe() != 0)
- msg_fatal("the master command must not run as a set-uid process");
+ msg_fatal("the master command must not run as a set-uid process");*/
/*
* Process JCL.
@@ -392,8 +392,10 @@ int main(int argc, char **argv)
* all MTA processes cleanly. Give up if we can't separate from our
* parent process. We're not supposed to blow away the parent.
*/
+ /*
if (debug_me == 0 && master_detach != 0 && setsid() == -1 && getsid(0) != getpid())
msg_fatal("unable to set session and process group ID: %m");
+ */
/*
* Make some room for plumbing with file descriptors. XXX This breaks
diff --git a/src/postfix/postfix.c b/src/postfix/postfix.c
index 183c825..007c805 100644
--- a/src/postfix/postfix.c
+++ b/src/postfix/postfix.c
@@ -450,12 +450,12 @@ int main(int argc, char **argv)
* privileges for selected operations. That's right - it takes privileges
* to toss privileges.
*/
- if (getuid() != 0) {
+ /*if (getuid() != 0) {
msg_error("to submit mail, use the Postfix sendmail command");
msg_fatal("the postfix command is reserved for the superuser");
}
if (unsafe() != 0)
- msg_fatal("the postfix command must not run as a set-uid process");
+ msg_fatal("the postfix command must not run as a set-uid process");*/
/*
* Parse switches.
diff --git a/src/postsuper/postsuper.c b/src/postsuper/postsuper.c
index 9dabb5d..e678565 100644
--- a/src/postsuper/postsuper.c
+++ b/src/postsuper/postsuper.c
@@ -1150,10 +1150,10 @@ int main(int argc, char **argv)
* the secondary groups, the process environment, and so on. Otherwise,
* accidents can happen. If not with Postfix, then with other software.
*/
- if (unsafe() != 0)
+ /*if (unsafe() != 0)
msg_fatal("this postfix command must not run as a set-uid process");
if (getuid())
- msg_fatal("use of this command is reserved for the superuser");
+ msg_fatal("use of this command is reserved for the superuser");*/
/*
* Parse JCL.
diff --git a/src/util/chroot_uid.c b/src/util/chroot_uid.c
index 4a7660f..d5d4e67 100644
--- a/src/util/chroot_uid.c
+++ b/src/util/chroot_uid.c
@@ -55,10 +55,11 @@ void chroot_uid(const char *root_dir, const char *user_name)
msg_fatal("unknown user: %s", user_name);
uid = pwd->pw_uid;
gid = pwd->pw_gid;
+ /*
if (setgid(gid) < 0)
msg_fatal("setgid(%ld): %m", (long) gid);
if (initgroups(user_name, gid) < 0)
- msg_fatal("initgroups: %m");
+ msg_fatal("initgroups: %m");*/
}
/*
@@ -74,9 +75,11 @@ void chroot_uid(const char *root_dir, const char *user_name)
/*
* Drop the user privileges.
*/
+ /*
if (user_name != 0)
if (setuid(uid) < 0)
msg_fatal("setuid(%ld): %m", (long) uid);
+ */
/*
* Give the desperate developer a clue of what is happening.
diff --git a/src/util/set_eugid.c b/src/util/set_eugid.c
index ef35380..ed96a69 100644
--- a/src/util/set_eugid.c
+++ b/src/util/set_eugid.c
@@ -53,7 +53,7 @@
void set_eugid(uid_t euid, gid_t egid)
{
- int saved_errno = errno;
+/* int saved_errno = errno;
if (geteuid() != 0)
if (seteuid(0))
@@ -67,4 +67,4 @@ void set_eugid(uid_t euid, gid_t egid)
if (msg_verbose)
msg_info("set_eugid: euid %ld egid %ld", (long) euid, (long) egid);
errno = saved_errno;
-}
+*/}
diff --git a/src/util/set_ugid.c b/src/util/set_ugid.c
index bbcb901..5a7a48b 100644
--- a/src/util/set_ugid.c
+++ b/src/util/set_ugid.c
@@ -44,7 +44,7 @@
void set_ugid(uid_t uid, gid_t gid)
{
- int saved_errno = errno;
+/* int saved_errno = errno;
if (geteuid() != 0)
if (seteuid(0) < 0)
@@ -58,4 +58,4 @@ void set_ugid(uid_t uid, gid_t gid)
if (msg_verbose > 1)
msg_info("setugid: uid %ld gid %ld", (long) uid, (long) gid);
errno = saved_errno;
-}
+*/}
Taken from https://bugs.gentoo.org/show_bug.cgi?id=544610
--- a/makedefs 2015-03-27 00:25:29.103726341 +0100
+++ a/makedefs 2015-03-27 00:32:14.657061042 +0100
@@ -500,7 +500,8 @@
: ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
: ${PLUGIN_LD="${CC-gcc} -shared"}
;;
- Linux.3*) SYSTYPE=LINUX3
+ Linux.*)
+ SYSTYPE=LINUX
case "$CCARGS" in
*-DNO_DB*) ;;
*-DHAS_DB*) ;;
--- a/src/util/sys_defs.h 2015-03-27 00:36:21.203728543 +0100
+++ a/src/util/sys_defs.h 2015-03-27 00:36:09.657061839 +0100
@@ -756,7 +756,7 @@
/*
* LINUX.
*/
+#if defined(LINUX2) || defined(LINUX)
-#if defined(LINUX2) || defined(LINUX3)
#define SUPPORTED
#include <sys/types.h>
#define UINT32_TYPE unsigned int
diff --git a/makedefs b/makedefs
index dd5f256..e90880e 100644
--- a/makedefs
+++ b/makedefs
@@ -299,13 +299,13 @@ case "$SYSTEM.$RELEASE" in
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# No, we're not going to try db1 db2 db3 etc.
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
@@ -372,12 +372,12 @@ EOF
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
@@ -403,12 +403,12 @@ EOF
elif [ -f /usr/include/db/db.h ]
then
CCARGS="$CCARGS -I/usr/include/db"
- else
+ #else
# On a properly installed system, Postfix builds
# by including <db.h> and by linking with -ldb
- echo "No <db.h> include file found." 1>&2
- echo "Install the appropriate db*-devel package first." 1>&2
- exit 1
+ #echo "No <db.h> include file found." 1>&2
+ #echo "Install the appropriate db*-devel package first." 1>&2
+ #exit 1
fi
SYSLIBS="-ldb"
;;
[buildout]
extends =
../git/buildout.cfg
[userhosts]
recipe = plone.recipe.command
stop-on-error = true
update-command = ${:command}
command = cd ${userhosts-get:location} && make
# For convenience (one section to build & know result path)
location = ${userhosts-get:location}/userhosts
[userhosts-get]
recipe = slapos.recipe.build:gitclone
repository = http://git.erp5.org/repos/userhosts.git
revision = d3080ad4b82c91dc14fd2ad2a8e9b2512e600c2a
git-executable = ${git:location}/bin/git
location = ${buildout:parts-directory}/userhosts
...@@ -167,6 +167,7 @@ setup(name=name, ...@@ -167,6 +167,7 @@ setup(name=name,
'proactive = slapos.recipe.proactive:Recipe', 'proactive = slapos.recipe.proactive:Recipe',
'publish = slapos.recipe.publish:Recipe', 'publish = slapos.recipe.publish:Recipe',
'publish.serialised = slapos.recipe.publish:Serialised', 'publish.serialised = slapos.recipe.publish:Serialised',
'publish-early = slapos.recipe.publish_early:Recipe',
'publishsection = slapos.recipe.publish:PublishSection', 'publishsection = slapos.recipe.publish:PublishSection',
'publishurl = slapos.recipe.publishurl:Recipe', 'publishurl = slapos.recipe.publishurl:Recipe',
'readline = slapos.recipe.readline:Recipe', 'readline = slapos.recipe.readline:Recipe',
...@@ -192,17 +193,19 @@ setup(name=name, ...@@ -192,17 +193,19 @@ setup(name=name,
'slapmonitor = slapos.recipe.slapmonitor:MonitorRecipe', 'slapmonitor = slapos.recipe.slapmonitor:MonitorRecipe',
'slapmonitor-xml = slapos.recipe.slapmonitor:MonitorXMLRecipe', 'slapmonitor-xml = slapos.recipe.slapmonitor:MonitorXMLRecipe',
'slapreport = slapos.recipe.slapreport:Recipe', 'slapreport = slapos.recipe.slapreport:Recipe',
'softwaretype = slapos.recipe.softwaretype:Recipe', 'softwaretype = slapos.recipe.softwaretype:Recipe', # BBB
'sphinx= slapos.recipe.sphinx:Recipe', 'sphinx= slapos.recipe.sphinx:Recipe',
'squid = slapos.recipe.squid:Recipe', 'squid = slapos.recipe.squid:Recipe',
'sshkeys_authority = slapos.recipe.sshkeys_authority:Recipe', 'sshkeys_authority = slapos.recipe.sshkeys_authority:Recipe',
'sshkeys_authority.request = slapos.recipe.sshkeys_authority:Request', 'sshkeys_authority.request = slapos.recipe.sshkeys_authority:Request',
'stunnel = slapos.recipe.stunnel:Recipe', 'stunnel = slapos.recipe.stunnel:Recipe',
'switch-softwaretype = slapos.recipe.switch_softwaretype:Recipe',
'symbolic.link = slapos.recipe.symbolic_link:Recipe', 'symbolic.link = slapos.recipe.symbolic_link:Recipe',
'tidstorage = slapos.recipe.tidstorage:Recipe', 'tidstorage = slapos.recipe.tidstorage:Recipe',
'trac = slapos.recipe.trac:Recipe', 'trac = slapos.recipe.trac:Recipe',
'urlparse = slapos.recipe._urlparse:Recipe', 'urlparse = slapos.recipe._urlparse:Recipe',
'uuid = slapos.recipe._uuid:Recipe', 'uuid = slapos.recipe._uuid:Recipe',
'userinfo = slapos.recipe.userinfo:Recipe',
'vifib = slapos.recipe.vifib:Recipe', 'vifib = slapos.recipe.vifib:Recipe',
'waitfor = slapos.recipe.waitfor:Recipe', 'waitfor = slapos.recipe.waitfor:Recipe',
'webchecker = slapos.recipe.web_checker:Recipe', 'webchecker = slapos.recipe.web_checker:Recipe',
......
...@@ -57,7 +57,9 @@ class Recipe(GenericBaseRecipe): ...@@ -57,7 +57,9 @@ class Recipe(GenericBaseRecipe):
else: else:
raise ValueError('Unsupported scheme %s' % scheme) raise ValueError('Unsupported scheme %s' % scheme)
ip = self.options['ip'] ip_list = self.options['ip']
if isinstance(ip_list, basestring):
ip_list = [ip_list]
backend_path = self.options.get('backend-path', '/') backend_path = self.options.get('backend-path', '/')
vhost_template_name = self.getTemplateFilename('vhost.in') vhost_template_name = self.getTemplateFilename('vhost.in')
apache_config_file = self.createFile( apache_config_file = self.createFile(
...@@ -78,7 +80,7 @@ class Recipe(GenericBaseRecipe): ...@@ -78,7 +80,7 @@ class Recipe(GenericBaseRecipe):
'port': port, 'port': port,
'backend': ('%s/%s' % (backend.rstrip('/'), backend_path.strip('/'))).rstrip('/'), 'backend': ('%s/%s' % (backend.rstrip('/'), backend_path.strip('/'))).rstrip('/'),
'ssl_enable': ssl_enable, 'ssl_enable': ssl_enable,
}) for (port, backend) in backend_list), }) for (port, backend) in backend_list for ip in ip_list),
}, },
) )
) )
......
############################################################################## ##############################################################################
# #
# Copyright (c) 2012 Vifib SARL and Contributors. All Rights Reserved. # Copyright (c) 2012-2014 Vifib SARL and Contributors. All Rights Reserved.
# #
# WARNING: This program as such is intended to be used by professional # WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsibility of assessing all potential # programmers who take the whole responsibility of assessing all potential
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
############################################################################## ##############################################################################
from slapos.recipe.librecipe import GenericBaseRecipe from slapos.recipe.librecipe import GenericBaseRecipe
import os
import sys import sys
import urlparse import urlparse
...@@ -36,31 +35,25 @@ class Recipe(GenericBaseRecipe): ...@@ -36,31 +35,25 @@ class Recipe(GenericBaseRecipe):
""" """
def install(self): def install(self):
parsed = urlparse.urlparse(self.options['mysql-url']) mysql = urlparse.urlsplit(self.options['mysql-url'])
mysql_connection_string = "%(database)s@%(hostname)s:%(port)s "\ zope = urlparse.urlsplit(self.options['zope-url'])
"%(username)s %(password)s" % dict( # Note: raises when there is more than a single element in path, as it's
database=parsed.path.split('/')[1], # not supported by manage_addERP5Site anyway.
hostname=parsed.hostname, _, zope_path = zope.path.split('/')
port=parsed.port, return [self.createExecutable(
username=parsed.username,
password=parsed.password
)
zope_parsed = urlparse.urlparse(self.options['zope-url'])
config = dict(
python_path=sys.executable,
user=zope_parsed.username,
password=zope_parsed.password,
site_id=zope_parsed.path.split('/')[1],
host="%s:%s" % (zope_parsed.hostname, zope_parsed.port),
sql_connection_string=mysql_connection_string,
)
# Runners
runner_path = self.createExecutable(
self.options['runner-path'], self.options['runner-path'],
self.substituteTemplate(self.getTemplateFilename('erp5_bootstrap.in'), self.substituteTemplate(
config)) self.getTemplateFilename('erp5_bootstrap.in'),
{
return [runner_path] 'python_path': sys.executable,
'base_url': urlparse.urlunsplit((zope.scheme, zope.netloc, '', '', '')),
'site_id': zope_path,
'sql_connection_string': '%(database)s@%(hostname)s:%(port)s %(username)s %(password)s' % {
'database': mysql.path.split('/')[1],
'hostname': mysql.hostname,
'port': mysql.port,
'username': mysql.username,
'password': mysql.password
},
},
))]
#!%(python_path)s #!%(python_path)s
import httplib
import urllib import urllib
import base64
user = "%(user)s"
password = "%(password)s"
host = "%(host)s"
site_id = "%(site_id)s"
erp5_catalog_storage = 'erp5_mysql_innodb_catalog'
mysql_url = "%(sql_connection_string)s"
header_dict = {'Authorization': 'Basic %%s' %% \
base64.encodestring('%%s:%%s' %% (user, password)).strip(),
'Referer':'http://%%s/manage_addProduct/ERP5/addERP5Site' %% host}
zope_connection = httplib.HTTPConnection(host)
# Check if an ERP5 site is already created, as ERP5 does support having
# 2 instances in the same zope, and this script should not destroy user data
zope_connection.request('GET', '/isERP5SitePresent', headers=header_dict)
result = zope_connection.getresponse()
if result.status == 204: # and (result.read() == "False"): import ssl
if hasattr(ssl, '_create_unverified_context'):
# Use a new connection ssl._create_default_https_context = ssl._create_unverified_context
zope_connection = httplib.HTTPConnection(host)
def isSuccess(response):
# Create the expected ERP5 instance return 200 <= response.code < 300
zope_connection.request(
'POST', '/manage_addProduct/ERP5/manage_addERP5Site', base_url = %(base_url)r
urllib.urlencode({ response = urllib.urlopen(base_url + '/isERP5SitePresent')
'id': site_id, if isSuccess(response) and response.read() == '':
'erp5_catalog_storage': erp5_catalog_storage, mysql_url = %(sql_connection_string)r
response = urllib.urlopen(
base_url + '/manage_addProduct/ERP5/manage_addERP5Site',
data=urllib.urlencode({
'id': %(site_id)r,
'erp5_catalog_storage': 'erp5_mysql_innodb_catalog',
'erp5_sql_connection_string': mysql_url, 'erp5_sql_connection_string': mysql_url,
'cmf_activity_sql_connection_string': mysql_url, 'cmf_activity_sql_connection_string': mysql_url,
}), }),
headers=header_dict) )
# Wait for the erp5 response, to prevent multiple requests if not isSuccess(response):
# been done by the same script. raise ValueError('Failed creating site, status=%%i: %%s' %% (response.code, response.read()))
result = zope_connection.getresponse()
# Read result make sure the site really finished to
#created the ERP5 site.
result.read()
print "ERP5 site created." print "ERP5 site created."
...@@ -38,12 +38,25 @@ class Recipe(GenericBaseRecipe): ...@@ -38,12 +38,25 @@ class Recipe(GenericBaseRecipe):
# XXX: assume existence of 100 test databases, because slaves are not # XXX: assume existence of 100 test databases, because slaves are not
# functional yet in slapos: testdb_0...testdb_100, with testuser_N # functional yet in slapos: testdb_0...testdb_100, with testuser_N
mysql_template = "%s@%s:%s %s %s" mysql_template = "%s@%s:%s %s %s"
mysql_url_list = self.options.get('mysql-url-list')
if mysql_url_list is None:
mysql_parsed = urlparse.urlparse(self.options['mysql-url']) mysql_parsed = urlparse.urlparse(self.options['mysql-url'])
for i in range(0, 100): for i in range(0, 100):
mysql_connection_string_list.append(mysql_template % ('testdb_%s'% i, mysql_connection_string_list.append(mysql_template % ('testdb_%s'% i,
mysql_parsed.hostname, mysql_parsed.port, 'testuser_%s'% i, mysql_parsed.password)) mysql_parsed.hostname, mysql_parsed.port, 'testuser_%s'% i, mysql_parsed.password))
mysql_connection_string = mysql_template % ('erp5_test', mysql_parsed.hostname, mysql_connection_string = mysql_template % ('erp5_test', mysql_parsed.hostname,
mysql_parsed.port, 'erp5_test', mysql_parsed.password) mysql_parsed.port, 'erp5_test', mysql_parsed.password)
else:
for mysql_url in mysql_url_list:
mysql_parsed = urlparse.urlparse(mysql_url)
mysql_connection_string_list.append(mysql_template % (
mysql_parsed.path.lstrip('/'),
mysql_parsed.hostname,
mysql_parsed.port,
mysql_parsed.username,
mysql_parsed.password,
))
mysql_connection_string = mysql_connection_string_list.pop()
cloudooo_parsed = urlparse.urlparse(self.options['cloudooo-url']) cloudooo_parsed = urlparse.urlparse(self.options['cloudooo-url'])
memcached_parsed = urlparse.urlparse(self.options['memcached-url']) memcached_parsed = urlparse.urlparse(self.options['memcached-url'])
kumofs_parsed = urlparse.urlparse(self.options['kumofs-url']) kumofs_parsed = urlparse.urlparse(self.options['kumofs-url'])
......
...@@ -48,6 +48,9 @@ class Recipe(object): ...@@ -48,6 +48,9 @@ class Recipe(object):
- storage-path: plain-text persistent storage for password, - storage-path: plain-text persistent storage for password,
that can only be accessed by the user that can only be accessed by the user
(default: ${buildout:parts-directory}/${:_buildout_section_name_}) (default: ${buildout:parts-directory}/${:_buildout_section_name_})
If storage-path is empty, the recipe does not save the password, which is
fine it is saved by other means, e.g. using the publish-early recipe.
""" """
def __init__(self, buildout, name, options): def __init__(self, buildout, name, options):
...@@ -57,16 +60,17 @@ class Recipe(object): ...@@ -57,16 +60,17 @@ class Recipe(object):
except KeyError: except KeyError:
self.storage_path = options['storage-path'] = os.path.join( self.storage_path = options['storage-path'] = os.path.join(
buildout['buildout']['parts-directory'], name) buildout['buildout']['parts-directory'], name)
passwd = None
if self.storage_path:
try: try:
with open(self.storage_path) as f: with open(self.storage_path) as f:
passwd = f.read() passwd = f.read()
except IOError as e: except IOError as e:
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
passwd = None self.update = self.install
if not passwd: if not passwd:
passwd = self.generatePassword(int(options_get('bytes', '8'))) passwd = self.generatePassword(int(options_get('bytes', '8')))
self.update = self.install
self.passwd = passwd self.passwd = passwd
# Password must not go into .installed file, for 2 reasons: # Password must not go into .installed file, for 2 reasons:
# security of course but also to prevent buildout to always reinstall. # security of course but also to prevent buildout to always reinstall.
......
...@@ -17,7 +17,8 @@ def runMysql(args): ...@@ -17,7 +17,8 @@ def runMysql(args):
# XXX: Protect with proper root password # XXX: Protect with proper root password
# XXX: Follow http://dev.mysql.com/doc/refman/5.0/en/default-privileges.html # XXX: Follow http://dev.mysql.com/doc/refman/5.0/en/default-privileges.html
popen = subprocess.Popen([conf['mysql_install_binary'], popen = subprocess.Popen([conf['mysql_install_binary'],
'--skip-name-resolve', '--no-defaults', '--defaults-file=%s' % conf['configuration_file'],
'--skip-name-resolve',
'--datadir=%s' % conf['data_directory'], '--datadir=%s' % conf['data_directory'],
'--basedir=%s' % conf['mysql_base_directory']], '--basedir=%s' % conf['mysql_base_directory']],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
...@@ -66,7 +67,7 @@ def updateMysql(args): ...@@ -66,7 +67,7 @@ def updateMysql(args):
with open(script_filename) as script_file: with open(script_filename) as script_file:
conf['mysql_script'] = script_file.read() conf['mysql_script'] = script_file.read()
while True: while True:
mysql_upgrade_list = [conf['mysql_upgrade_binary'], '--no-defaults', '--user=root'] mysql_upgrade_list = [conf['mysql_upgrade_binary'], '--user=root']
if 'socket' in conf: if 'socket' in conf:
mysql_upgrade_list.append('--socket=' + conf['socket']) mysql_upgrade_list.append('--socket=' + conf['socket'])
mysql_upgrade = subprocess.Popen(mysql_upgrade_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) mysql_upgrade = subprocess.Popen(mysql_upgrade_list, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
...@@ -80,7 +81,7 @@ def updateMysql(args): ...@@ -80,7 +81,7 @@ def updateMysql(args):
print "MySQL database upgraded with result:\n%s" % result print "MySQL database upgraded with result:\n%s" % result
else: else:
print "No need to upgrade MySQL database" print "No need to upgrade MySQL database"
mysql_list = [conf['mysql_binary'].strip(), '--no-defaults', '-B', '--user=root'] mysql_list = [conf['mysql_binary'].strip(), '-B', '--user=root']
if 'socket' in conf: if 'socket' in conf:
mysql_list.append('--socket=' + conf['socket']) mysql_list.append('--socket=' + conf['socket'])
mysql = subprocess.Popen(mysql_list, stdin=subprocess.PIPE, mysql = subprocess.Popen(mysql_list, stdin=subprocess.PIPE,
......
...@@ -53,6 +53,7 @@ def Zope2InitUser(path, username, password): ...@@ -53,6 +53,7 @@ def Zope2InitUser(path, username, password):
class Recipe(GenericBaseRecipe): class Recipe(GenericBaseRecipe):
def _options(self, options): def _options(self, options):
if 'password' not in options:
options['password'] = self.generatePassword() options['password'] = self.generatePassword()
def install(self): def install(self):
...@@ -101,26 +102,21 @@ class Recipe(GenericBaseRecipe): ...@@ -101,26 +102,21 @@ class Recipe(GenericBaseRecipe):
# Always provide a URL-Type # Always provide a URL-Type
append("file://" + link) append("file://" + link)
zope_environment = dict( zope_environment = {
TMP=self.options['tmp-path'], 'TMP': self.options['tmp-path'],
TMPDIR=self.options['tmp-path'], 'TMPDIR': self.options['tmp-path'],
HOME=self.options['tmp-path'], 'HOME': self.options['tmp-path'],
PATH=self.options['bin-path'], 'PATH': self.options['bin-path'],
TZ=self.options['timezone'], 'TZ': self.options['timezone'],
) }
# longrequestlogger product which requires environment settings # longrequestlogger product which requires environment settings
longrequest_logger_file = self.options.get('longrequest-logger-file', None) longrequest_logger_file = self.options.get('longrequest-logger-file', None)
longrequest_logger_timeout = \
self.options.get('longrequest-logger-timeout', None)
longrequest_logger_interval= \
self.options.get('longrequest-logger-interval', None)
if longrequest_logger_file: if longrequest_logger_file:
# add needed zope configuration # add needed zope configuration
zope_environment.update( zope_environment['longrequestlogger_file'] = longrequest_logger_file
**dict(longrequestlogger_file = longrequest_logger_file, zope_environment['longrequestlogger_timeout'] = self.options.get('longrequest-logger-timeout', None)
longrequestlogger_timeout = longrequest_logger_timeout, zope_environment['longrequestlogger_interval'] = self.options.get('longrequest-logger-interval', None)
longrequestlogger_interval = longrequest_logger_interval))
# configure default Zope2 zcml # configure default Zope2 zcml
open(self.options['site-zcml'], 'w').write(open(self.getTemplateFilename( open(self.options['site-zcml'], 'w').write(open(self.getTemplateFilename(
......
...@@ -76,11 +76,15 @@ class Storage(NeoBaseRecipe): ...@@ -76,11 +76,15 @@ class Storage(NeoBaseRecipe):
_binding_port_mandatory = False _binding_port_mandatory = False
def _getOptionList(self): def _getOptionList(self):
return [ r = [
'-d', self.options['database-parameters'], '-d', self.options['database-parameters'],
'-a', self.options['database-adapter'], '-a', self.options['database-adapter'],
'-w', self.options['wait-database'], '-w', self.options['wait-database'],
] ]
engine = self.options.get('engine')
if engine: # old versions of NEO don't support -e
r += '-e', engine
return r
class Admin(NeoBaseRecipe): class Admin(NeoBaseRecipe):
def _getOptionList(self): def _getOptionList(self):
...@@ -92,6 +96,7 @@ class Master(NeoBaseRecipe): ...@@ -92,6 +96,7 @@ class Master(NeoBaseRecipe):
r = [ r = [
'-p', options['partitions'], '-p', options['partitions'],
'-r', options['replicas'], '-r', options['replicas'],
'-A', options['autostart'],
] ]
for x in (('-C', options['upstream-cluster']), for x in (('-C', options['upstream-cluster']),
('-M', options['upstream-masters'])): ('-M', options['upstream-masters'])):
......
...@@ -32,15 +32,19 @@ CONNECTION_PARAMETER_STRING = 'connection-' ...@@ -32,15 +32,19 @@ CONNECTION_PARAMETER_STRING = 'connection-'
class Recipe(GenericSlapRecipe): class Recipe(GenericSlapRecipe):
def _install(self): def _install(self):
publish_dict = dict() publish_dict = {}
options = self.options.copy() done = set()
del options['recipe'] extends = [self.name]
slave_reference = options.pop('-slave-reference', None) while extends:
for k, v in options.iteritems(): name = extends.pop()
done.add(name)
for k, v in self.buildout[name].iteritems():
if k[:1] == '-': if k[:1] == '-':
continue if k == '-extends':
extends += set(v.split()) - done
elif k != 'recipe':
publish_dict[k] = v publish_dict[k] = v
self._setConnectionDict(publish_dict, slave_reference) self._setConnectionDict(publish_dict, self.options.get('-slave-reference'))
return [] return []
def _setConnectionDict(self, publish_dict, slave_reference=None): def _setConnectionDict(self, publish_dict, slave_reference=None):
......
##############################################################################
#
# Copyright (c) 2010 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.
#
##############################################################################
import slapos.slap
from slapos.recipe.librecipe import unwrap, wrap
from slapos.recipe.librecipe import GenericSlapRecipe
class Recipe(GenericSlapRecipe):
"""
Early initialization of published parameters.
The '-init' option defines parameters that should be published before
requesting any partitions, and how they are initialized.
Example:
[publish-early]
recipe = slapos.cookbook:publish-early
-init =
foo gen-foo:x
bar gen-bar:y
bar = z
[gen-foo]
...
[publish]
recipe = slapos.cookbook:publish.serialised
-extends = publish-early
...
${publish-early:foo} is initialized with the value of the published
parameter 'foo', or ${gen-foo:x} if it hasn't been published yet
(and in this case, it is published immediately as a way to save the value).
${publish-early:bar} is forced to 'z' (${gen-bar:y} ignored):
a line like 'bar = z' is usually rendered conditionally with Jinja2.
"""
def __init__(self, buildout, name, options):
GenericSlapRecipe.__init__(self, buildout, name, options)
published_dict = None
publish = False
publish_dict = {}
for line in options['-init'].splitlines():
if line:
k, v = line.split()
if k not in options:
if published_dict is None:
self.slap.initializeConnection(self.server_url, self.key_file,
self.cert_file)
computer_partition = self.slap.registerComputerPartition(
self.computer_id, self.computer_partition_id)
published_dict = unwrap(
computer_partition.getConnectionParameterDict())
try:
publish_dict[k] = published_dict[k]
except KeyError:
section, key = v.split(":")
publish_dict[k] = self.buildout[section][key]
publish = True
if publish:
computer_partition.setConnectionDict(wrap(publish_dict))
options.update(publish_dict)
install = update = lambda self: None
##############################################################################
#
# Copyright (c) 2014 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 advised 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
##############################################################################
import os, subprocess, sys
class Recipe:
def __init__(self, buildout, name, options):
self.buildout = buildout
self.options = options
self.name = name
self.software_type = buildout["slap-configuration"]["slap-software-type"]
section, key = self.options[self.software_type].split(":")
self.base = self.buildout[section][key]
def install(self):
# XXX-Antoine: We gotta find a better way to do this. I tried to check
# out how slapgrid-cp was running buildout. But it is worse than that.
args = sys.argv[:]
for x in self.buildout["slap-connection"].iteritems():
args.append("slap-connection:%s=%s" % x)
for x in "directory", "eggs-directory", "develop-eggs-directory":
args.append("buildout:%s=%s" % (x, self.buildout["buildout"][x]))
args.append("buildout:installed=.installed-%s.cfg" % self.name)
# Options.get (from zc.buildout) should deserialize.
try:
override = self.options["override"][self.software_type]
except (KeyError, TypeError):
buildout = self.base
else:
# unfortunately, buildout:extends does not work when given at command line
buildout = os.path.join(self.buildout["buildout"]["parts-directory"],
self.name + ".cfg")
with open(override) as src, open(buildout, "w", 0) as dst:
dst.write("[buildout]\nextends = %s\n\n" % self.base + src.read())
subprocess.check_call(args + ["-oc", buildout])
return []
update = install
import grp
import os
import pwd
class Recipe(object):
"""
Provide POSIX information about the user that is currently running buildout.
"""
def __init__(self, buildout, name, options):
pinfo = pwd.getpwuid(os.getuid())
options['pw-name'] = pinfo.pw_name
options['pw-uid'] = pinfo.pw_uid
options['pw-gid'] = pinfo.pw_gid
options['pw-dir'] = pinfo.pw_dir
options['pw-shell'] = pinfo.pw_shell
ginfo = grp.getgrgid(os.getgid())
options['gr-name'] = ginfo.gr_name
options['gr-gid'] = ginfo.gr_gid
install = update = lambda self: []
Available ``software-type`` values
==================================
- ``default``
Recommended for production use.
- ``create-erp5-site``
Automated creation of ERP5Site instance, for easy deployment.
Usage in production discouraged due to the increased risk of data loss.
Notes
=====
This software release is not intended to be accessed directly, but through a
front-end instance which is expected to contains the RewriteRules_ (or
equivalent) needed to relocate Zope's urls via its VirtualHostMonster_. See the
``frontend`` erp5 instance parameter.
Included cloudooo partition is **deprecated**. It is not recommended for
intensive usage. See the ``cloudooo`` Software Release to setup a cloudooo
cluster, more suitable for intensive usage.
Port ranges
===========
This software release assigns the following port ranges by default:
==================== ==========
Partition type Port range
==================== ==========
memcached-persistent 2000-2009
memcached-volatile 2010-2019
cloudooo 2020-2024
smtp 2025-2029
neo (admin & master) 2050-2051
mariadb 2099
zeo 2100-2149
balancer 2150-2199
zope 2200-*
==================== ==========
Non-zope partitions are unique in an ERP5 cluster, so you shouldn't have to
care about them as a user (but a Software Release developer needs to know
them).
Zope partitions should be assigned port ranges starting at 2200, incrementing
by some value which depends on how many zope process you want per partition
(see the ``port-base`` parameter in ``zope-partition-dict``).
Notes to the Software Release developper: These ranges are not strictly
defined. Not each port is actually used so one may reduce alread-assigned
ranges if needed (ex: memcached partitions use actually fewer ports). There
should be enough room for evolution (as between smtp and mariadb types). It is
important to not allocate any port after 2200 as user may have assigned ports
to his zope processes.
.. _RewriteRules: http://httpd.apache.org/docs/current/en/mod/mod_rewrite.html#rewriterule
.. _VirtualHostMonster: http://docs.zope.org/zope2/zope2book/VirtualHosting.html
TODO: improve
Instance Parameters
===================
Zope Parameters
---------------
Needed by software-type development (default) and zope.
frontend-software-url
~~~~~~~~~~~~~~~~~~~~~
Software URL of an existing frontend.
XXX: meaning should change (or it will go away) in order to be resilient to
software updates - as they are visible at software-url level.
If it is not provided, no frontend will be requested.
frontend-instance-guid
~~~~~~~~~~~~~~~~~~~~~~
GUID of frontend instance.
Not perfect yet: if that instance is replaced, slaves have to be reconfigured.
Mandatory only if frontend-software-url is also provided.
XXX: should be complemented (or replaced) by more flexible and precise
criteria.
frontend-software-type (optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Frontend software type as defined by the software relase at
frontend-software-url.
frontend-domain (optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Domain name frontend must recognise as belonging to this instance.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"required": ["tcpv4-port"],
"properties": {
"tcpv4-port": {
"allOf": [{
"$ref": "#/definitions/tcpv4port"
}, {
"description": "Start allocating ports at this value, going upward"
}]
},
"font-url-list": {
"description": "List of URLs from which fonts are to be downloaded",
"default": [],
"items": {
"type": "string"
},
"type": "array"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Parameters to instantiate ERP5",
"additionalProperties": false,
"properties": {
"sla-dict": {
"description": "Where to request instances. Each key is a query string for criterions (e.g. \"computer_guid=foo\"), and each value is a list of partition references.",
"additionalProperties": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
},
"type": "object"
},
"site-id": {
"description": "ERP5Site object's id",
"default": "erp5",
"type": "string"
},
"timezone": {
"description": "Zope's timezone. Possible values are determined by host's libc, and typically come from a separate package (tzdata, ...)",
"default": "UTC",
"type": "string"
},
"deadlock-debugger-password": {
"description": "Password for /manage_debug_threads",
"type": "string"
},
"inituser-login": {
"description": "Login of the initial/rescue user",
"default": "zope",
"type": "string"
},
"inituser-password": {
"description": "Password of the initial/rescue user",
"type": "string"
},
"developer-list": {
"description": "List of logins which should get the Developper role (required to modify portal_components' content), defaulting to inituser-login's value",
"items": {
"pattern": "/^\\S+$/",
"type": "string"
},
"uniqueItems": true,
"type": "array"
},
"hostalias-dict": {
"description": "Hostname-to-hostname mapping",
"default": {},
"additionalProperties": {
"description": "A hostname to which current entry will resolve",
"type": "string"
},
"type": "object"
},
"hosts-dict": {
"description": "Host entries to be used in addition to and/or overriding auto-generated ones (erp5-catalog-0, erp5-cloudooo, erp5-memcached-persistent, erp5-memcached-volatile and erp5-smtp)",
"patternProperties": {
".*": {
"description": "An IP or domain name to which current entry will resolve",
"type": "string"
}
},
"type": "object"
},
"frontend": {
"description": "Front-end slave instance request parameters",
"properties": {
"software-url": {
"description": "Front-end's software type. If this parameter is empty, no front-end instance is requested. Else, sla-dict must specify 'frontend' which is a special value matching all frontends (e.g. {\"instance_guid=bar\": [\"frontend\"]}).",
"default": "",
"type": "string"
},
"domain": {
"description": "The domain name to request front-end to respond as.",
"default": "",
"type": "string"
},
"software-type": {
"description": "Request a front-end slave instance of this software type.",
"default": "RootSoftwareInstance",
"type": ""
}
},
"type": "object"
},
"zope-partition-dict": {
"description": "Zope layout definition",
"default": {"1": {}},
"patternProperties": {
".*": {
"additionalProperties": false,
"properties": {
"family": {
"description": "The family this partition is part of. For example: 'public', 'admin', 'backoffice', 'web-service'... Each family gets its own balancer entry. It has no special meaning for the system.",
"default": "default",
"type": "string"
},
"instance-count": {
"description": "Number of Zopes to setup on this partition",
"default": 1,
"type": "integer"
},
"thread-amount": {
"description": "Number of worker threads for each created Zope process",
"default": 4,
"type": "integer"
},
"timerserver-interval": {
"description": "Timerserver tick perdiod, in seconds, or 0 to disable",
"default": 5,
"type": "integer"
},
"webdav": {
"description": "Serve webdav queries, implies timerserver-interval=0 (disabled). Mixing webdav and non-webdav nodes in a single family will give unspecified results.",
"default": false,
"type": "boolean"
},
"longrequest-logger-interval": {
"description": "Period, in seconds, with which LongRequestLogger polls worker thread stack traces, or -1 to disable",
"default": -1,
"type": "integer"
},
"longrequest-logger-timeout": {
"description": "Transaction duration after which LongRequestLogger will start logging its stack trace, in seconds",
"default": 1,
"type": "integer"
},
"port-base": {
"allOf": [{
"$ref": "#/definitions/tcpv4port"
}, {
"description": "Start allocating ports at this value. Useful if one needs to make several partitions share the same port range (ie, several partitions bound to a single address)",
"default": 2200
}]
}
},
"type": "object"
}
},
"type": "object"
},
"kumofs": {
"description": "Persistent memcached service",
"additionalProperties": {
"$ref": "./instance-kumofs-schema.json#properties"
},
"type": "object"
},
"memcached": {
"description": "Volatile memcached service",
"additionalProperties": {
"$ref": "./instance-kumofs-schema.json#properties"
},
"type": "object"
},
"cloudooo": {
"description": "Format conversion service",
"additionalProperties": {
"$ref": "./instance-cloudooo-schema.json#properties"
},
"type": "object"
},
"mariadb": {
"description": "Relational database service",
"additionalProperties": {
"$ref": "./instance-mariadb-schema.json#properties"
},
"type": "object"
},
"zodb-zeo": {
"description": "Common settings ZEO servers",
"properties": {
"tcpv4-port": {
"allOf": [{
"$ref": "#/definitions/tcpv4port"
}, {
"description": "Start allocating ports at this value, going upward"
}]
},
"backup-periodicity": {
"description": "When to backup, specified in the same format as for systemd.time(7) calendar events (years & seconds not supported, DoW & DoM can not be combined). Enter 'never' to disable backups.",
"default": "daily",
"type": "string"
},
"tidstorage-repozo-path": {
"description": "Directory for backup timestamp and tidstorage status files.",
"default": "~/srv/backup/tidstorage",
"type": "string"
}
},
"type": "object"
},
"zodb": {
"description": "Zope Object DataBase mountpoints. See https://github.com/zopefoundation/ZODB/blob/3.10/src/ZODB/component.xml for extra options.",
"items": {
"required": ["type"],
"properties": {
"name": {
"description": "Database name",
"default": "main",
"type": "string"
},
"mount-point": {
"description": "Mount point",
"default": "/",
"type": "string"
},
"type": {
"description": "Storage type",
"enum": ["zeo", "neo"],
"type": "string"
},
"server": {
"description": "Instantiate a server. If missing, 'storage-dict' must contain the necessary properties to mount the ZODB. For ZEO, the partition reference is 'zodb'. For NEO, they are 'neo-0', 'neo-1', ...",
"anyOf": [
{"$ref": "./instance-zeo-schema.json"},
{"$ref": "../neoppod/instance-neo-input-schema.json"}
]
},
"storage-dict": {
"description": "Storage configuration. For NEO, 'logfile' is automatically set (see http://git.erp5.org/gitweb/neoppod.git/blob/HEAD:/neo/client/component.xml for other settings).",
"additionalProperties": {"type": "string"},
"type": "object"
}
},
"additionalProperties": {"type": "string"},
"type": "object"
},
"type": "array"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Values returned by ERP5 instantiation",
"properties": {
"hosts-dict": {
"description": "Hosts mapping, including auto-generated entries",
"patternProperties": {
".*": {
"description": "IP or domain names current entry resolves to",
"type": "string"
}
},
"type": "object"
},
"site-id": {
"description": "Chosen ERP5Site object identifier",
"type": "string"
},
"inituser-login": {
"description": "Initial user login",
"type": "string"
},
"inituser-password": {
"description": "Initial user password",
"type": "string"
},
"kumofs-url": {
"description": "Persistent memcached access information",
"type": "string"
},
"memcached-url": {
"description": "Volatile memcached access information",
"type": "string"
},
"cloudooo-url": {
"description": "Conversion service access information",
"type": "string"
},
"mariadb-url": {
"description": "Relational database access information",
"type": "string"
}
},
"patternProperties": {
"family-.*": {
"description": "Zope family access information",
"type": "string"
}
},
"type": "object"
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"required": ["tcpv4-port"],
"properties": {
"tcpv4-port": {
"allOf": [{
"$ref": "#/definitions/tcpv4port"
}, {
"description": "Start allocating ports at this value, going upward"
}]
},
"ram-storage-size": {
"description": "If 0 use disk storage, otherwise use ram and limit data size to this many megabytes",
"default": 0,
"type": "integer"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"required": ["tcpv4-port"],
"properties": {
"tcpv4-port": {
"allOf": [{
"$ref": "#/definitions/tcpv4port"
}, {
"description": "Start allocating ports at this value, going downward"
}]
},
"database-list": {
"description": "Databases to create and respective user credentials getting all privileges on it",
"default": [{
"name": "erp5",
"user": "user",
"password": "insecure"
}],
"minItems": 1,
"items": {
"required": ["name", "user", "password"],
"properties": {
"name": {
"description": "Database name",
"type": "string"
},
"user": {
"description": "User name",
"type": "string"
},
"password": {
"description": "User password",
"type": "string"
}
},
"type": "object"
},
"type": "array"
},
"test-database-amount": {
"description": "The number of test databases to create, adding auto-generated entries to database-list",
"default": 1,
"minimum": 0,
"type": "integer"
},
"catalog-backup": {
"description": "Backup control knobs",
"properties": {
"full-retention-days": {
"description": "How many days full backups must be retained, -1 meaning full backups are disabled and 0 meaning no expiration",
"default": 7,
"minimum": -1,
"type": "integer"
},
"incremental-retention-days": {
"description": "How many days incremental backups (binlogs) must be retained, -1 meaning incremental backups are disabled and 0 meaning no expiration, defaulting to full-retention-days' value",
"minimum": -1,
"type": "integer"
}
},
"type": "object"
},
"backup-periodicity": {
"description": "When to backup, specified in the same format as for systemd.time(7) calendar events (years & seconds not supported, DoW & DoM can not be combined).",
"default": "daily",
"type": "string"
},
"innodb-buffer-pool-size": {
"description": "See MariaDB documentation on innodb_buffer_pool_size",
"minimum": 0,
"type": "integer"
},
"innodb-log-file-size": {
"description": "See MariaDB documentation on innodb_log_file_size",
"minimum": 0,
"type": "integer"
},
"innodb-log-buffer-size": {
"description": "See MariaDB documentation on innodb_log_buffer_size",
"minimum": 0,
"type": "integer"
},
"long-query-time": {
"description": "Number of seconds above which long queries are logged",
"minimum": 0,
"default": 1,
"type": "number"
},
"relaxed-writes": {
"description": "When enabled, sets innodb_flush_log_at_trx_commit = 0, innodb_flush_method = nosync, innodb_doublewrite = 0 and sync_frm = 0 - RTFM, those options are dangerous",
"default": false,
"type": "boolean"
},
"ssl": {
"description": "Enable and define SSL support for network connections",
"default": {},
"properties": {
"ca-crt": {
"description": "Certificate Authority's certificate, in PEM format",
"type": "string"
},
"crt": {
"description": "Server's certificate, in PEM format (mandatory to enable SSL support)",
"type": "string"
},
"key": {
"description": "Server's key, in PEM format (mandatory to enable SSL support)",
"type": "string"
},
"crl": {
"description": "Server's certificate revocation list, in PEM format",
"type": "string"
},
"cipher": {
"description": "Permissible cipher specifications, separated by colons",
"type": "string"
}
},
"type": "object"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"additionalProperties": false,
"properties": {
"backup": {
"description": "'%(backup)s' is expanded to partition's ZODB backup path (typically 'srv/backup/zodb'), and %(name)s with the export id",
"default": "%(backup)s/%(name)s",
"type": "string"
},
"family": {
"description": "Opaque name used to regroup/separate mountpoints under different ZEO processes (must be valid as a file name and as a ConfigParser section name)",
"default": "default",
"pattern": "^[^<>:\"/\\|?*\\]\\[ ]*$",
"type": "string"
},
"path": {
"description": "FileStorage file path, '%(zodb)s' occurrences are replaced with the path to partition's srv/zodb directory, and %(name)s with the export id",
"default": "%(zodb)s/%(name)s.fs",
"type": "string"
}
},
"type": "object"
}
...@@ -53,7 +53,7 @@ mysqld-binary = ${mariadb:location}/bin/mysqld ...@@ -53,7 +53,7 @@ mysqld-binary = ${mariadb:location}/bin/mysqld
mysqldump-binary = ${mariadb:location}/bin/mysqldump mysqldump-binary = ${mariadb:location}/bin/mysqldump
gzip-binary = $${buildout:gzip-binary} gzip-binary = $${buildout:gzip-binary}
zcat-binary = ${gzip:location}/bin/zcat zcat-binary = ${gzip:location}/bin/zcat
mysql-tzinfo-to-sql-binary = ${mariadb:location}/bin/mysql_tzinfo_to_sql
[certificate-authority] [certificate-authority]
recipe = slapos.cookbook:certificate_authority recipe = slapos.cookbook:certificate_authority
......
...@@ -48,7 +48,7 @@ mode = 0644 ...@@ -48,7 +48,7 @@ mode = 0644
[instance-mariadb] [instance-mariadb]
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/instance-mariadb.cfg url = ${:_profile_base_location_}/instance-mariadb.cfg
md5sum = d160bb15d8d3a3913706a4ed29c49388 md5sum = 79f86f8c74335b2b9ec81d6a02164cbf
output = ${buildout:directory}/template-mariadb.cfg output = ${buildout:directory}/template-mariadb.cfg
mode = 0644 mode = 0644
......
Software types
==============
Which software type is an entry point and can be used for root software
instance.
Parameters are expected to be passed as of *.serialised recipes expect them.
Minimal parameters::
```
<?xml version='1.0' encoding='utf-8'?>
<instance>
<parameter id="_">{
"cluster": "dummy",
}</parameter>
</instance>
```
For each available key in the outmost dict are described below.
default (default)
-----------------
Deploy a NEO cluster.
'cluster' (str, mandatory)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Cluster unique identifier. Your last line of defense against mixing up neo
clusters and corrupting your data. Choose a unique value for each of your
cluster.
'partitions' (int, optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of partitions. You cannot change this value once you created a cluster.
Defautls to 12.
'replicas' (int, optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of replicates.
Defaults to 0 (no resilience).
'mysql-storage-count' (int, optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of MySQL-based storage nodes to deploy. One master node is deployed
along with each storage.
Defaults to 1.
'admin-count' (int, optional)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Number of admin nodes to deploy.
Defaults to 1.
{% if slap_software_type not in ( {% import "root_common" as common_macro with context %}
mysql_storage_software_type,
admin_software_type,
) -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set part_list = [] -%}
{% set master_list = [] -%}
{% set admin_list = [] -%}
[request-common]
recipe = slapos.cookbook:request
software-url = ${slap-connection:software-release-url}
sla-computer_guid = ${slap-connection:computer-id}
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
config-cluster = {{ slapparameter_dict['cluster'] }}
[node-base]
< = request-common
config-masters = ${all-masters:addresses}
[mysql-storage-base]
< = request-common
config-partitions = {{ slapparameter_dict.get('partitions', 12) }}
config-replicas = {{ slapparameter_dict.get('replicas', 0) }}
software-type = {{ mysql_storage_software_type }}
[mysql-storage-request-base] [request-common]
< = mysql-storage-base <= request-common-base
return = master
[admin-base]
< = node-base
return = admin
software-type = {{ admin_software_type }}
{{ common_macro.request_neo(slapparameter_dict, 'neo', 'node-') }}
[publish] [publish]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:publish.serialised
masters = ${all-masters:addresses} neo-masters = ${node-0-final:connection-masters}
admins = ${all-admins:addresses} neo-admins = ${node-0-final:connection-admins}
{{ common_macro.common_section() }}
{% for node_number in range(slapparameter_dict.get('mysql-storage-count', 1)) -%}
{% set section_id = 'storage-%i' % (node_number, ) -%}
{% set final_section_id = 'final-' ~ section_id -%}
{% do master_list.append(section_id) -%}
[{{ section_id }}]
< = mysql-storage-request-base
name = {{ section_id }}
[{{ section(final_section_id) }}]
< = mysql-storage-base
node-base
name = {{ section_id }}
{% endfor -%}
{% for node_number in range(slapparameter_dict.get('admin-count', 1)) -%}
{% set section_id = 'admin-%i' % (node_number, ) -%}
{% do admin_list.append(section_id)%}
[{{ section(section_id) }}]
< = admin-base
name = {{ section_id }}
{% endfor -%}
[buildout]
parts =
{{ part_list | join('\n\t') }}
publish
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[all-masters]
addresses = {% for master in master_list -%}
{{ '${' + master + ':connection-master}' -}}
{% if not loop.last %} {% endif -%}
{% endfor %}
[all-admins]
addresses = {% for admin in admin_list -%}
{{ '${' + admin + ':connection-admin}' -}}
{% if not loop.last %} {% endif -%}
{% endfor %}
{% endif -%}
[buildout]
parts = switch-softwaretype
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[jinja2-template-base]
recipe = slapos.recipe.template:jinja2
filename = ${:_buildout_section_name_}.cfg
rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/${:filename}
extensions = jinja2.ext.do
extra-context =
context =
key ipv4_set slap-configuration:ipv4
key ipv6_set slap-configuration:ipv6
key slapparameter_dict slap-configuration:configuration
raw logrotate_cfg {{ template_logrotate_base }}
raw bin_directory {{ bin_directory }}
${:extra-context}
[neo-admin]
<= jinja2-template-base
template = {{ neo_admin }}
[neo-master]
<= jinja2-template-base
template = {{ neo_master }}
[neo-storage-mysql]
<= jinja2-template-base
template = {{ neo_storage_mysql }}
extra-context =
key master_cfg neo-master:rendered
key admin_cfg neo-admin:rendered
raw mariadb_location {{ mariadb_location }}
raw template_neo_my_cnf {{ template_neo_my_cnf }}
[buildout]
parts =
cron-entry-logrotate
[cron]
recipe = slapos.cookbook:cron
cron-entries = ${logrotate-directory:cron-entries}
dcrond-binary = {{ dcron_location }}/sbin/crond
crontabs = ${logrotate-directory:crontabs}
cronstamps = ${logrotate-directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
binary = ${logrotate-directory:services}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${logrotate-directory:bin}/cron_simplelogger
log = ${logrotate-directory:log}/cron.log
[logrotate]
recipe = slapos.cookbook:logrotate
logrotate-entries = ${logrotate-directory:logrotate-entries}
backup = ${logrotate-directory:logrotate-backup}
logrotate-binary = {{ logrotate_location }}/usr/sbin/logrotate
gzip-binary = {{ gzip_location }}/bin/gzip
gunzip-binary = {{ gzip_location }}/bin/gunzip
wrapper = ${logrotate-directory:bin}/logrotate
conf = ${logrotate-directory:etc}/logrotate.conf
state-file = ${logrotate-directory:srv}/logrotate.status
[cron-entry-logrotate]
recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
[logrotate-directory]
recipe = slapos.cookbook:mkdirectory
cron-entries = ${:etc}/cron.d
cronstamps = ${:etc}/cronstamps
crontabs = ${:etc}/crontabs
logrotate-backup = ${:backup}/logrotate
logrotate-entries = ${:etc}/logrotate.d
bin = ${buildout:directory}/bin
srv = ${buildout:directory}/srv
backup = ${:srv}/backup
etc = ${buildout:directory}/etc
services = ${:etc}/run
log = ${buildout:directory}/var/log
[buildout] [buildout]
parts = parts +=
neo-admin-run-wrapper
neo-admin-promise neo-admin-promise
logrotate-admin
eggs-directory = {{eggs_directory}}
develop-eggs-directory = {{develop_eggs_directory}}
offline = true
[neo-admin] [neo-admin]
recipe = slapos.cookbook:neoppod.admin recipe = slapos.cookbook:neoppod.admin
binary = {{bin_directory}}/neoadmin binary = {{bin_directory}}/neoadmin
wrapper = ${directory:bin}/neoadmin wrapper = ${directory:etc_run}/neoadmin
logfile = ${directory:log}/neoadmin.log logfile = ${directory:log}/neoadmin.log
ip = ${publish:ip} ip = ${publish:ip}
port = ${publish:port} port = ${publish:port-admin}
cluster = ${slap-parameter:cluster} cluster = {{ dumps(slapparameter_dict['cluster']) }}
masters = ${slap-parameter:masters} masters = ${publish:masters}
[publish]
recipe = slapos.cookbook:publish
# TODO: make port a partition parameter
# TODO: stop using slap-network-information
ip = [${slap-network-information:global-ipv6}]
port = 10002
admin = ${:ip}:${:port}
[neo-admin-run-wrapper]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:run}
link-binary = ${neo-admin:wrapper}
[directory]
recipe = slapos.cookbook:mkdirectory
promises = ${buildout:directory}/etc/promises
run = ${buildout:directory}/etc/run
log = ${buildout:directory}/var/log
bin = ${buildout:directory}/bin
[neo-admin-promise] [neo-admin-promise]
recipe = slapos.cookbook:check_port_listening recipe = slapos.cookbook:check_port_listening
hostname = ${neo-admin:ip} hostname = ${neo-admin:ip}
port = ${neo-admin:port} port = ${neo-admin:port}
path = ${directory:promises}/neo-admin-promise path = ${directory:promises}/neo-admin-promise
[logrotate-admin]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = neo-admin
log = ${neo-admin:logfile}
post = {{ bin_directory }}/slapos-kill -n neoadmin -s RTMIN+1 ${:log}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Parameters to instantiate a NEO cluster. See https://git.erp5.org/gitweb/neoppod.git/blob/HEAD:/neo.conf?js=1 for more information.",
"additionalProperties": false,
"required": ["cluster"],
"properties": {
"cluster": {
"description": "Cluster unique identifier. Your last line of defense against mixing up NEO clusters and corrupting your data. Choose a unique value for each of your cluster.",
"type": "string"
},
"partitions": {
"description": "Number of partitions. You cannot change this value once you created a cluster.",
"default": 12,
"type": "integer"
},
"replicas": {
"description": "Number of replicates.",
"default": 0,
"type": "integer"
},
"upstream-cluster": {
"description": "Identifier of the cluster to backup.",
"type": "string"
},
"upstream-masters": {
"description": "Master nodes in the cluster to backup.",
"type": "string"
},
"sla-dict": {
"description": "[NEO SR only] Where to request instances. Each key is a query string for criterions (e.g. \"computer_guid=foo\"), and each value is a list of partition references ('node-0', 'node-1', ...).",
"additionalProperties": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
},
"type": "object"
},
"node-list": {
"description": "List of dictionaries containing parameters for each node.",
"items": {
"description": "Dictionary containing parameters required to configure individual nodes.",
"default": {},
"properties": {
"admin": {
"description": "Port of admin node. 0 to disable.",
"default": 2050,
"type": "integer"
},
"master": {
"description": "Port of master node. 0 to disable.",
"default": 2051,
"type": "integer"
},
"storage-count": {
"description": "Number of storage nodes to deploy. One master and one admin node is deployed with each storage.",
"default": 1,
"type": "integer"
},
"mysql": {
"description": "Dictionary containing parameters for MySQL.",
"default": {},
"properties": {
"relaxed-writes": {
"description": "When enabled, sets innodb_flush_log_at_trx_commit = 0, innodb_flush_method = nosync, innodb_doublewrite = 0 and sync_frm = 0 - RTFM, those options are dangerous",
"default": false,
"type": "boolean"
}
},
"additionalProperties": {
"description": "To configure important parameters like innodb_buffer_pool_size, tokudb_cache_size, etc.",
"type": "string"
},
"type": "object"
},
"engine": {
"description": "Configures storage engine, currently only InnoDB and TokuDB are supported. Defaults to NEO's default.",
"type": "string"
}
},
"type": "object"
},
"type": "array"
}
},
"type": "object"
}
[buildout] [buildout]
parts = parts +=
neo-master-run-wrapper
neo-master-promise neo-master-promise
eggs-directory = {{eggs_directory}} logrotate-master
develop-eggs-directory = {{develop_eggs_directory}}
offline = true
[neo-master] [neo-master]
recipe = slapos.cookbook:neoppod.master recipe = slapos.cookbook:neoppod.master
binary = {{bin_directory}}/neomaster binary = {{bin_directory}}/neomaster
wrapper = ${directory:bin}/neomaster wrapper = ${directory:etc_run}/neomaster
logfile = ${directory:log}/neomaster.log logfile = ${directory:log}/neomaster.log
ip = ${publish:ip} ip = ${publish:ip}
port = ${publish:port} port = ${publish:port-master}
cluster = ${slap-parameter:cluster} cluster = {{ dumps(slapparameter_dict['cluster']) }}
partitions = ${slap-parameter:partitions} partitions = {{ slapparameter_dict['partitions'] }}
replicas = ${slap-parameter:replicas} replicas = {{ slapparameter_dict['replicas'] }}
masters = ${slap-parameter:masters} upstream-cluster = {{ dumps(slapparameter_dict['upstream-cluster']) }}
upstream-masters = {{ dumps(slapparameter_dict['upstream-masters']) }}
[publish] autostart = {{ slapparameter_dict['autostart'] }}
recipe = slapos.cookbook:publish # "masters" parameter is not provided when just requesting a partition.
# TODO: make port a partition parameter # No actual installation takes place at that time
# TODO: stop using slap-network-information # (slapos.cookbook:neoppod.master raises), but cfg expansion must succeed. So
ip = [${slap-network-information:global-ipv6}] # this default value is required.
port = 10000 masters = ${publish:masters}
master = ${:ip}:${:port}
[neo-master-run-wrapper]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:run}
link-binary = ${neo-master:wrapper}
[directory]
recipe = slapos.cookbook:mkdirectory
promises = ${buildout:directory}/etc/promises
run = ${buildout:directory}/etc/run
log = ${buildout:directory}/var/log
bin = ${buildout:directory}/bin
[neo-master-promise] [neo-master-promise]
recipe = slapos.cookbook:check_port_listening recipe = slapos.cookbook:check_port_listening
...@@ -44,9 +28,10 @@ hostname = ${neo-master:ip} ...@@ -44,9 +28,10 @@ hostname = ${neo-master:ip}
port = ${neo-master:port} port = ${neo-master:port}
path = ${directory:promises}/neo-master-promise path = ${directory:promises}/neo-master-promise
[slap-parameter] [logrotate-master]
# "masters" parameter is not provided when just requesting a partition. recipe = slapos.cookbook:logrotate.d
# No actuall installation takes place at that time logrotate-entries = ${logrotate:logrotate-entries}
# (slapos.cookbook:neoppod.master raises), but cfg expansion must succeed. So backup = ${logrotate:backup}
# this default value is required. name = neo-master
masters = log = ${neo-master:logfile}
post = {{ bin_directory }}/slapos-kill -n neomaster -s RTMIN+1 ${:log}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "Values returned by NEO instantiation",
"properties": {
"masters": {
"description": "Connection parameters of all the master nodes",
"type": "string"
},
"admins": {
"description": "Connection parameters of all the admin nodes",
"type": "string"
}
},
"type": "object"
}
[buildout] {% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
extends = {{ master_cfg }} {% set part_list = [] -%}
parts += neo-storage-run-wrapper {% set init_list = [] -%}
[mariadb-instance]
recipe = slapos.cookbook:generic.mysql
user = user
database = neo
conf-file = ${directory:etc}/mariadb.cnf [mysqld]
# No networking (ip & port options) recipe = slapos.cookbook:generic.mysql.wrap_mysqld
output = ${directory:etc_run}/mariadb
binary = ${:mysql-base-directory}/bin/mysqld
configuration-file = ${my-cnf:rendered}
data-directory = ${directory:srv_mariadb} data-directory = ${directory:srv_mariadb}
bin-directory = ${directory:bin} mysql-install-binary = ${:mysql-base-directory}/scripts/mysql_install_db
pid-file = ${directory:var_run}/mariadb.pid mysql-base-directory = {{ mariadb_location }}
[my-cnf-parameters]
socket = ${directory:var_run}/mariadb.sock socket = ${directory:var_run}/mariadb.sock
data-directory = ${mysqld:data-directory}
pid-file = ${directory:var_run}/mariadb.pid
error-log = ${directory:log}/mariadb_error.log error-log = ${directory:log}/mariadb_error.log
slow-query-log = ${directory:log}/mariadb_slowquery.log slow-query-log = ${directory:log}/mariadb_slowquery.log
extra-dict = {{ dumps(slapparameter_dict.get('mysql', {})) }}
init-file = ${init-script:rendered}
wrapper = ${directory:etc_run}/mariadb [my-cnf]
update-wrapper = ${directory:etc_run}/mariadb_update recipe = slapos.recipe.template:jinja2
mysql-base-directory = {{ mariadb_location }} extensions = jinja2.ext.do
mysql-binary = {{ mariadb_location }}/bin/mysql rendered = ${directory:etc}/mariadb.cnf
mysql-install-binary = {{ mariadb_location }}/scripts/mysql_install_db template = {{ template_neo_my_cnf }}
mysql-upgrade-binary = {{ mariadb_location }}/bin/mysql_upgrade context = section parameter_dict my-cnf-parameters
mysqld-binary = {{ mariadb_location }}/bin/mysqld
mroonga = {% set master_list = [] -%}
{% set admin_list = [] -%}
{% for k, v in slapparameter_dict.iteritems() -%}
{% if k.startswith('master-') and v -%}
{% do master_list.append(v) -%}
{% endif -%}
{% if k.startswith('admin-') and v -%}
{% do admin_list.append(v) -%}
{% endif -%}
{% endfor -%}
[publish]
recipe = slapos.cookbook:publish.serialised
# TODO: make port a partition parameter
ip = {{ (ipv4_set | list)[0] }}
{% set admin = slapparameter_dict.get('admin', 2050) -%}
{% set master = slapparameter_dict.get('master', 2051) -%}
{% if master -%}
port-master = {{ master }}
master = ${:ip}:${:port-master}
{% else -%}
master =
{% endif -%}
{% if admin -%}
port-admin = {{ admin }}
admin = ${:ip}:${:port-admin}
{% else -%}
admin =
{% endif -%}
masters = {{ ' '.join(sorted(master_list)) }}
{%- if admin_list %}
admins = {{ ' '.join(sorted(admin_list)) }}
{%- endif %}
[neo-storage] [neo-storage]
recipe = slapos.cookbook:neoppod.storage recipe = slapos.cookbook:neoppod.storage
binary = {{ bin_directory }}/neostorage binary = {{ bin_directory }}/neostorage
wrapper = ${directory:bin}/neostorage ip = ${publish:ip}
logfile = ${directory:log}/neostorage.log cluster = {{ dumps(slapparameter_dict['cluster']) }}
ip = [${slap-network-information:global-ipv6}] masters = ${publish:masters}
cluster = ${slap-parameter:cluster}
masters = ${slap-parameter:masters}
database-adapter = MySQL database-adapter = MySQL
database-parameters = ${mariadb-instance:user}:${mariadb-instance:password}@${mariadb-instance:database}${mariadb-instance:socket}
wait-database = 60 wait-database = 60
engine = {{ slapparameter_dict.get('engine', '') }}
[logrotate-storage]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
{% for i in range(slapparameter_dict.get('storage-count', 1)) -%}
{% set storage_id = 'neo-storage-' ~ i -%}
[{{ section(storage_id) }}]
< = neo-storage
wrapper = ${directory:etc_run}/{{ 'neostorage-' ~ i }}
logfile = ${directory:log}/{{ 'neostorage-' ~ i }}.log
{% do init_list.append('CREATE DATABASE IF NOT EXISTS neo' ~ i ~ ';') -%}
database-parameters = root@neo{{ i }}${my-cnf-parameters:socket}
[{{ section('logrotate-storage-' ~ i) }}]
< = logrotate-storage
name = {{ storage_id }}
log = {{ '${' + storage_id + ':logfile}' }}
post = {{ bin_directory }}/slapos-kill -n neostorage -s RTMIN+1 ${:log}
[neo-storage-run-wrapper] {% endfor -%}
recipe = slapos.cookbook:symbolic.link [init-script]
target-directory = ${directory:etc_run} recipe = slapos.recipe.template:jinja2
link-binary = ${neo-storage:wrapper} # XXX: is there a better location ?
rendered = ${directory:etc}/mariadb_initial_setup.sql
template = inline:
{{ init_list | join('\n\t') }}
[directory] [directory]
recipe = slapos.cookbook:mkdirectory
promises = ${buildout:directory}/etc/promises
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc etc = ${buildout:directory}/etc
var = ${buildout:directory}/var var = ${buildout:directory}/var
etc_run = ${:etc}/run etc_run = ${:etc}/run
var_run = ${:var}/run var_run = ${:var}/run
srv_mariadb = ${buildout:directory}/srv/mariadb srv_mariadb = ${buildout:directory}/srv/mariadb
log = ${buildout:directory}/var/log
[logrotate-mysql]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = mariadb
log = ${my-cnf-parameters:error-log} ${my-cnf-parameters:slow-query-log}
post = ${mysqld:mysql-base-directory}/bin/mysql --defaults-file="${my-cnf:rendered}" -e "FLUSH LOGS"
[buildout]
extends =
{{ logrotate_cfg }}
{%- if master %}
{{ master_cfg }}
{%- endif %}
{%- if admin %}
{{ admin_cfg }}
{%- endif %}
parts +=
{{ '\n '.join(part_list) }}
logrotate-mysql
{% set admin_software_type = 'neo-admin' -%}
{% set mysql_storage_software_type = 'neo-storage-mysql' -%}
[buildout] [buildout]
parts = switch-softwaretype extends = {{ instance_common_cfg }}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slap-connection] [jinja2-template-base]
computer-id = ${slap_connection:computer_id} rendered = ${buildout:parts-directory}/${:_buildout_section_name_}.cfg
partition-id = ${slap_connection:partition_id}
server-url = ${slap_connection:server_url}
software-release-url = ${slap_connection:software_release_url}
key-file = ${slap_connection:key_file}
cert-file = ${slap_connection:cert_file}
[slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[neo-cluster] [neo-cluster]
recipe = slapos.recipe.template:jinja2 <= jinja2-template-base
template = {{ cluster }} template = {{ cluster }}
rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/cluster.cfg extra-context =
extensions = jinja2.ext.do import urlparse urlparse
context = import-list =
key eggs_directory buildout:eggs-directory rawfile root_common {{ root_common }}
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-configuration:slap-software-type
key slapparameter_dict slap-configuration:configuration
raw admin_software_type {{ admin_software_type }}
raw mysql_storage_software_type {{ mysql_storage_software_type }}
[switch-softwaretype] [switch-softwaretype]
recipe = slapos.cookbook:softwaretype recipe = slapos.cookbook:switch-softwaretype
default = ${neo-cluster:rendered} override = {{ dumps(override_switch_softwaretype |default) }}
{{ admin_software_type }} = {{ neo_admin }} default = neo-cluster:rendered
{{ mysql_storage_software_type }} = {{ neo_storage_mysql }} # BBB
RootSoftwareInstance = ${:default}
neo = neo-storage-mysql:rendered
{% macro assert(x) %}{{ ("",)[not x] }}{% endmacro -%}
{% set socket = parameter_dict['socket'] -%}
{% set extra_dict = parameter_dict['extra-dict'] -%}
[mysqld]
skip_networking
socket = {{ socket }}
datadir = {{ parameter_dict['data-directory'] }}
pid_file = {{ parameter_dict['pid-file'] }}
log_error = {{ parameter_dict['error-log'] }}
slow_query_log
slow_query_log_file = {{ parameter_dict['slow-query-log'] }}
init_file = {{ parameter_dict['init-file'] }}
log_warnings = 1
disable-log-bin
### Enables TokuDB
plugin-load = ha_tokudb
## The following settings come from ERP5 configuration.
max_allowed_packet = 128M
query_cache_size = 32M
innodb_locks_unsafe_for_binlog = 1
# Some dangerous settings you may want to uncomment temporarily
# if you only want performance or less disk access.
{% set x = '' if extra_dict.pop('relaxed-writes', False) else '#' -%}
{{x}}innodb_flush_log_at_trx_commit = 0
{{x}}innodb_flush_method = nosync
{{x}}innodb_doublewrite = 0
{{x}}sync_frm = 0
# Extra parameters.
{%- do extra_dict.setdefault('innodb_file_per_table', '0') %}
{%- for k, v in extra_dict.iteritems() %}
{%- do assert('-' not in k) %}
{{ k }} = {{ v }}
{%- endfor %}
# Force utf8 usage
collation_server = utf8_unicode_ci
character_set_server = utf8
skip_character_set_client_handshake
[client]
socket = {{ socket }}
user = root
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set part_list = [] -%}
{% set sla_dict = {} -%}
{% for sla, ref_list in slapparameter_dict.get('sla-dict', {}).iteritems() -%}
{% do sla_dict.update(dict.fromkeys(ref_list, sla)) -%}
{% endfor -%}
{% macro sla(name, required=False) -%}
{% if required or name in sla_dict -%}
{% for k, (v,) in urlparse.parse_qs(sla_dict.pop(name), strict_parsing=1).iteritems() -%}
sla-{{ k }} = {{ v }}
{% endfor -%}
{% else -%}
sla-computer_guid = ${slap-connection:computer-id}
{% endif -%}
{% endmacro -%}
{% macro common_section() -%}
[request-common-base]
recipe = slapos.cookbook:request.serialised
software-url = ${slap-connection:software-release-url}
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
[buildout]
parts =
publish
{{ part_list | join('\n\t') }}
{{- assert(not sla_dict, sla_dict) }}
{% endmacro -%}
{% macro request_neo(parameter_dict, software_type, prefix='node-') -%}
{% set section_id_list = [] -%}
[{{ prefix }}request-common]
<= request-common-base
config-cluster = {{ parameter_dict['cluster'] }}
{% set replicas = parameter_dict.get('replicas', 0) -%}
config-partitions = {{ dumps(parameter_dict.get('partitions', 12)) }}
config-replicas = {{ dumps(replicas) }}
config-upstream-cluster = {{ dumps(parameter_dict.get('upstream-cluster', '')) }}
config-upstream-masters = {{ dumps(parameter_dict.get('upstream-masters', '')) }}
software-type = {{ software_type }}
{% set node_list = parameter_dict.get('node-list', ({},)) -%}
{% set storage_count = [] -%}
{% for node in node_list -%}
{% do storage_count.append(node.get('storage-count', 1)) -%}
{% endfor -%}
config-autostart = {{ dumps(sum(storage_count)) }}
{% do assert(replicas < len(node_list)) -%}
{% for i, node in enumerate(node_list) -%}
{% set section_id = prefix ~ i -%}
{% do section_id_list.append(section_id) -%}
[{{ section_id }}-base]
name = {{ section_id }}
{% for k, v in node.iteritems() -%}
config-{{ k }} = {{ dumps(v) }}
{% endfor -%}
{{ sla(section_id) }}
[{{ section_id }}]
<= {{ prefix }}request-common
{{ section_id }}-base
return =
master
admin
{% endfor -%}
[final-base]
{% for i, section_id in enumerate(section_id_list) -%}
config-master-{{i}} = {{ '${' + section_id + ':connection-master}' }}
config-admin-{{i}} = {{ '${' + section_id + ':connection-admin}' }}
{% endfor -%}
{% for section_id in section_id_list -%}
[{{ section(section_id + '-final') }}]
<= {{ prefix }}request-common
final-base
{{ section_id }}-base
{% if loop.first -%}
return =
masters
admins
{% endif -%}
{% endfor -%}
{% endmacro -%}
# Note on LXML/END LXML: they delimit areas where lxml magic is needed. lxml is
# a slapos.cookbook dependency, so it should be fetched automatically. But when
# automatically fetched, it gets built against system headers/libs, which is
# forbidden in slapos. So we need to fetch lxml explicitly so it is properly
# built.
[buildout]
extends =
../../stack/slapos.cfg
../../component/dcron/buildout.cfg
../../component/gzip/buildout.cfg
../../component/logrotate/buildout.cfg
#LXML
../../component/lxml-python/buildout.cfg
#END LXML
../../component/python-2.7/buildout.cfg
../../component/mariadb/buildout.cfg
../../component/mysql-python/buildout.cfg
parts =
slapos-deps-eggs
slapos-cookbook-develop
slapos-cookbook
# NEO & dependencies
python2.7
mariadb
mysql-python
neoppod
[slapos.cookbook-repository]
branch = erp5-cluster
[slapos-deps-eggs]
recipe = zc.recipe.egg
eggs =
${lxml-python:egg}
slapos.toolbox
scripts =
slapos-kill
[template-logrotate-base]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}.in
rendered = ${buildout:directory}/${:filename}
filename = instance-logrotate-base.cfg
md5sum = af19ff0c7817df85987c69738fb083f2
context =
key dcron_location dcron:location
key gzip_location gzip:location
key logrotate_location logrotate:location
[download-base-neo]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/${:_buildout_section_name_}.cfg.in
# XXX: following mode should be the default
mode = 644
# XXX: must be rendered, not just dled
[instance-common]
recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:_buildout_section_name_}.cfg.in
rendered = ${buildout:directory}/${:_buildout_section_name_}.cfg
md5sum = e8f5a83580e9791a32c66f5935cb6840
context =
key bin_directory buildout:bin-directory
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key mariadb_location mariadb:location
key neo_admin instance-neo-admin:target
key neo_master instance-neo-master:target
key neo_storage_mysql instance-neo-storage-mysql:target
key template_logrotate_base template-logrotate-base:rendered
key template_neo_my_cnf template-neo-my-cnf:target
[root-common]
<= download-base-neo
md5sum = 26193dbb132d340c8ba919a616449a17
[instance-neo-admin]
<= download-base-neo
md5sum = 16d11f0fe74de06aebbadcff3527db1c
[instance-neo-master]
<= download-base-neo
md5sum = 023f08763dbba2319f58e5c597f7761d
[instance-neo-storage-mysql]
<= download-base-neo
md5sum = 5a61039c7a980e24519e1bbb1252e662
[template-neo-my-cnf]
<= download-base-neo
url = ${:_profile_base_location_}/my.cnf.in
md5sum = febd3ed58043ce1367b86cf6e4e69700
[neoppod]
recipe = zc.recipe.egg
eggs = neoppod[admin, ctl, master, storage-importer, storage-mysqldb]
ZODB3
ZODB3-patches = ${:_profile_base_location_}/../../component/egg-patch/ZODB3-3.10.5.patch
ZODB3-patch-options = -p1
[versions]
# patched eggs
ZODB3 = 3.10.5+SlapOSPatched001
# Note on LXML/END LXML: they delimit areas where lxml magic is needed. lxml is
# a slapos.cookbook dependency, so it should be fetched automatically. But when
# automatically fetched, it gets built against system headers/libs, which is
# forbidden in slapos. So we need to fetch lxml explicitly so it is properly
# built.
[buildout] [buildout]
extends = extends =
../../stack/slapos.cfg software-common.cfg
#LXML
../../component/lxml-python/buildout.cfg
#END LXML
../../component/python-2.7/buildout.cfg
../../component/mariadb/buildout.cfg
../../component/mysql-python/buildout.cfg
parts = parts +=
slapos-deps-eggs
slapos-cookbook
# NEO & dependencies
python2.7
mariadb
mysql-python
neoppod
# NEO instanciation # NEO instanciation
template-instance template
[slapos-deps-eggs]
recipe = zc.recipe.egg
eggs =
#LXML
${lxml-python:egg}
#END LXML
[base-template] [template]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
template = ${:_profile_base_location_}/${:filename}.in
rendered = ${buildout:directory}/${:filename}
extensions = jinja2.ext.do
extra-context =
context =
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key bin_directory buildout:bin-directory
${:extra-context}
[template-neo-master]
< = base-template
filename = instance-neo-master.cfg
md5sum = 8947620b15535b95163c11a0efab546e
[template-neo-storage-mysql]
< = base-template
filename = instance-neo-storage-mysql.cfg
md5sum = 518c8c41ce73f0b608fbb1c3b889ca1b
extra-context =
key mariadb_location mariadb:location
key master_cfg template-neo-master:rendered
[template-neo-admin]
< = base-template
filename = instance-neo-admin.cfg
md5sum = 987f69333c563898cab21455509f8024
[template-cluster]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/cluster.cfg.in
md5sum = edd46f8670421520ef20c786cd65d8c1
[template-instance]
< = base-template
template = ${:_profile_base_location_}/instance.cfg.in template = ${:_profile_base_location_}/instance.cfg.in
md5sum = 777c00a7dbcb145a75f980421a9b20b5
# XXX: "template.cfg" is hardcoded in instanciation recipe # XXX: "template.cfg" is hardcoded in instanciation recipe
filename = template.cfg rendered = ${buildout:directory}/template.cfg
md5sum = 17e761b371487b55b39da1c39ebb1bb6 context =
extra-context = key cluster cluster:target
key neo_master template-neo-master:rendered key instance_common_cfg instance-common:rendered
key neo_storage_mysql template-neo-storage-mysql:rendered key root_common root-common:target
key neo_admin template-neo-admin:rendered
key cluster template-cluster:target
[neoppod] [cluster]
recipe = zc.recipe.egg <= download-base-neo
eggs = neoppod[admin, master, storage-mysqldb] md5sum = ee8401a4e7d82bf488a57e3399f9ce48
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
PidFile "{{ parameter_dict['pid-file'] }}"
ServerAdmin admin@
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
TimeOut {{ parameter_dict['timeout'] }}
SSLCertificateFile {{ parameter_dict['cert'] }}
SSLCertificateKeyFile {{ parameter_dict['key'] }}
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLProtocol -ALL +SSLv3 +TLSv1
SSLHonorCipherOrder On
{% if parameter_dict['cipher'] -%}
SSLCipherSuite {{ parameter_dict['cipher'] }}
{% else -%}
SSLCipherSuite RC4-SHA:HIGH:!ADH
{%- endif %}
SSLSessionCache shmcb:{{ parameter_dict['ssl-session-cache'] }}(512000)
SSLProxyEngine On
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
CustomLog "{{ parameter_dict['access-log'] }}" combined
<Directory />
Options FollowSymLinks
AllowOverride None
Allow from all
</Directory>
RewriteEngine On
{% for port, _, backend, authentication in parameter_dict['backend-list'] -%}
{% for ip in parameter_dict['ip-list'] -%}
Listen {{ ip }}:{{ port }}
{% endfor -%}
<VirtualHost *:{{ port }}>
{% if authentication -%}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationPath {{ parameter_dict['crl'] }}
{% endif -%}
SSLEngine on
RewriteRule ^/(.*) {{ backend }}/$1 [L,P]
</VirtualHost>
{% endfor -%}
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
per partition. No more (undefined result), no less (IndexError).
-#}
# TODO: insert varnish between apache & haproxy.
# And think of a way to specify which urls goe through varnish, which go
# directly to haproxy. (maybe just passing literal configuration file chunk)
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set apache_ip_list = [ipv4] -%}
{% if ipv6_set -%}
{% set ipv6 = (ipv6_set | list)[0] -%}
{% do apache_ip_list.append('[' ~ ipv6 ~ ']') -%}
{% endif -%}
{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
runner-path = ${directory:services}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = {{ ipv4 }}
{% endif -%}
{% set haproxy_dict = {} -%}
{% set apache_dict = {} -%}
{% set next_port = slapparameter_dict['tcpv4-port'] -%}
{% for family_name, parameter_id_list in slapparameter_dict['zope-family-dict'].items() -%}
{% set zope_family_address_list = [] -%}
{% set has_webdav = [] -%}
{% for parameter_id in parameter_id_list -%}
{% set zope_address_list = slapparameter_dict[parameter_id] -%}
{% for zope_address, maxconn, webdav in zope_address_list -%}
{% if webdav -%}
{% do has_webdav.append(None) %}
{% endif -%}
{% if use_ipv6 -%}
[{{ section('zope-tunnel-' ~ next_port) }}]
< = zope-tunnel-base
base-name = {{ 'zeo-tunnel-' ~ next_port }}
ipv4-port = {{ next_port }}
ipv6-port = {{ zope_address.split(']:')[1] }}
ipv6 = {{ zope_address.split(']:')[0][1:] }}
{% set zope_effective_address = ipv4 ~ ":" ~ next_port -%}
{% set next_port = next_port + 1 -%}
{% else -%}
{% set zope_effective_address = zope_address -%}
{% endif -%}
{% do zope_family_address_list.append((zope_effective_address, maxconn, webdav)) -%}
{% endfor -%}
{% endfor -%}
{# Make rendering fail artificially if any family has no known backend.
# This is useful as haproxy's hot-reconfiguration mechanism is
# supervisord-incompatible.
# As jinja2 postpones KeyError until place-holder value is actually used,
# do a no-op getitem.
-#}
{% do zope_family_address_list[0][0] -%}
{% set haproxy_port = next_port -%}
{% set next_port = next_port + 1 -%}
{% do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{% if has_webdav -%}
{% set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
{% set external_scheme = 'webdavs' -%}
{% else %}
{% set internal_scheme = 'http' -%}
{% set external_scheme = 'https' -%}
{% endif -%}
{% set backend_path = slapparameter_dict['backend-path-dict'][family_name] -%}
{% set ssl_authentication = slapparameter_dict['ssl-authentication-dict'][family_name] -%}
{% do apache_dict.__setitem__(family_name, (next_port, external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ backend_path, ssl_authentication)) -%}
{% set next_port = next_port + 1 -%}
{% endfor -%}
[apache-certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ parameter_dict['openssl'] }}/bin/openssl
ca-dir = ${directory:ca-dir}
requests-directory = ${directory:requests}
wrapper = ${directory:services}/apache-ca
ca-private = ${directory:private}
ca-certs = ${directory:certs}
ca-newcerts = ${directory:newcerts}
ca-crl = ${directory:crl}
country-code = {{ slapparameter_dict['country-code'] }}
email = {{ slapparameter_dict['email'] }}
state = {{ slapparameter_dict['state'] }}
city = {{ slapparameter_dict['city'] }}
company = {{ slapparameter_dict['company'] }}
[haproxy-cfg-parameter-dict]
socket-path = ${directory:run}/haproxy.sock
server-check-path = {{ dumps(slapparameter_dict['haproxy-server-check-path']) }}
backend-dict = {{ dumps(haproxy_dict) }}
ip = {{ ipv4 }}
[haproxy-cfg]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-haproxy-cfg'] }}
rendered = ${directory:etc}/haproxy.cfg
context = section parameter_dict haproxy-cfg-parameter-dict
extensions = jinja2.ext.do
[{{ section('haproxy') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/haproxy
command-line = "{{ parameter_dict['haproxy'] }}/sbin/haproxy" -f "${haproxy-cfg:rendered}"
{# TODO: build socat and wrap it as "${directory:bin}/haproxy-ctl" to connect to "${haproxy-cfg-parameter-dict:socket-path}" #}
[apache-conf-ssl]
cert = ${directory:apache-conf}/apache.crt
key = ${directory:apache-conf}/apache.pem
ca-cert = ${directory:apache-conf}/ca.crt
crl = ${directory:apache-conf}/crl.pem
[apache-conf-parameter-dict]
backend-list = {{ dumps(apache_dict.values()) }}
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
# Apache 2.4's default value (60 seconds) can be a bit too short
timeout = 300
# Basic SSL server configuration
cert = ${apache-ssl:cert}
key = ${apache-ssl:key}
cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache
# Client x509 auth
{% if ssl_parameter_dict.get('ca-cert') and ssl_parameter_dict.get('ca-crl') -%}
ca-cert = {{ dumps(ssl_parameter_dict.get('ca-cert')) }}
crl = {{ dumps(ssl_parameter_dict.get('ca-crl')) }}
{% else -%}
ca-cert = ${apache-certificate-authority:ca-dir}/cacert.pem
crl = ${apache-certificate-authority:ca-crl}
{% endif -%}
[apache-conf]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-apache-conf'] }}
rendered = ${directory:apache-conf}/apache.conf
context = section parameter_dict apache-conf-parameter-dict
[{{ section('apache') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND
[{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/apache
hostname = {{ ipv4 }}
port = {{ apache_dict.values()[0][0] }}
[publish]
recipe = slapos.cookbook:publish.serialised
{% for family_name, (apache_port, scheme, _, _) in apache_dict.items() -%}
{{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}
[apache-ssl]
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
[logrotate-apache]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = apache
log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log}
post = {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
[directory]
recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
promise = ${directory:etc}/promise
services = ${:etc}/run
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
ca-dir = ${buildout:directory}/srv/ssl
requests = ${:ca-dir}/requests
private = ${:ca-dir}/private
certs = ${:ca-dir}/certs
newcerts = ${:ca-dir}/newcerts
crl = ${:ca-dir}/crl
[buildout]
extends = {{ logrotate_cfg }}
parts +=
publish
logrotate-apache
apache-certificate-authority
{{ part_list | join('\n ') }}
[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
services = ${:etc}/run
promise = ${:etc}/promise
[erp5-bootstrap]
recipe = slapos.cookbook:erp5.bootstrap
runner-path = ${directory:services}/erp5-bootstrap
{# Note: a random domain name will be picked if several point to the same IP -#}
{% set reverse_hosts = {} -%}
{% for x, y in publish['hosts-dict'].iteritems() -%}
{% do reverse_hosts.__setitem__(y, x) -%}
{% endfor -%}
{# XXX: Expect the first database to be the one to use for catalog. -#}
{% set mysql_parsed = urlparse.urlparse(publish['mariadb-database-list'][0]) -%}
mysql-url = {{ dumps(urlparse.urlunparse(mysql_parsed[:1] + (mysql_parsed.username + ":" + mysql_parsed.password + "@" + reverse_hosts.get(mysql_parsed.hostname, mysql_parsed.hostname) + ':' ~ mysql_parsed.port, ) + mysql_parsed[2:])) }}
{# Pick the first http[s] family found, they should be all equivalent anyway. -#}
{# Don't pick the https[s] configurated with ssl-authenticat=true. By convention, this family name contain 'service'. -#}
{% set family_list = [] -%}
{% for key, value in publish.items() -%}
{% if key.startswith('family-') and not 'service' in key and value.startswith('http') -%}
{% do family_list.append(value.split('://', 1)) -%}
{% endif -%}
{% endfor -%}
zope-url = {{ dumps(family_list[0][0] + '://' + publish['inituser-login'] + ':' + publish['inituser-password'] + '@' + family_list[0][1] + '/' + publish['site-id']) }}
[promise-erp5-site]
recipe = slapos.cookbook:check_url_available
url = ${erp5-bootstrap:zope-url}
path = ${directory:promise}/erp5-site
dash_path = {{ parameter_dict['dash-location'] }}/bin/dash
curl_path = {{ parameter_dict['curl-location'] }}/bin/curl
[buildout]
parts = promise-erp5-site
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
\ No newline at end of file
{% set frontend_dict = slapparameter_dict.get('frontend', {}) %}
{% set has_frontend = frontend_dict.get('software-url', '') != '' -%}
{% set site_id = slapparameter_dict.get('site-id', 'erp5') -%}
{% set inituser_login = slapparameter_dict.get('inituser-login', 'zope') -%}
{% set publish_dict = {'site-id': site_id, 'inituser-login': inituser_login} -%}
[request-common]
recipe = slapos.cookbook:request.serialised
software-url = ${slap-connection:software-release-url}
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
config-use-ipv6 = {{ dumps(slapparameter_dict.get('use-ipv6', False)) }}
{% macro request(name, software_type, config_key, config, ret={'url': True}) -%}
{% do config.update(slapparameter_dict.get(config_key, {})) -%}
{% set section = 'request-' ~ name -%}
[{{ section }}]
< = request-common
name = {{ name }}
software-type = {{ software_type }}
return = {{ ret.keys() | join(' ') }}
{% for ret, publish in ret.items() -%}
{% if publish -%}
{% do publish_dict.__setitem__(name ~ '-' ~ ret, '${' ~ section ~ ':connection-' ~ ret ~ '}')%}
{% endif -%}
{% endfor -%}
sla-computer_guid = {{ dumps(slapparameter_dict.get(config_key + '-computer-guid', computer_id)) }}
{% for option, value in config.items() -%}
config-{{ option }} = {{ dumps(value) }}
{% endfor -%}
{% endmacro -%}
{{ request('memcached-persistent', 'kumofs', 'kumofs', {'tcpv4-port': 2000}) }}
{{ request('memcached-volatile', 'kumofs', 'memcached', {'tcpv4-port': 2010, 'ram-storage-size': 64}) }}
{{ request('cloudooo', 'cloudooo', 'cloudooo', {'tcpv4-port': 2020}) }}
{{ request('mariadb', 'mariadb', 'mariadb', {'tcpv4-port': 2099}, {'database-list': True, 'test-database-list': True}) }}
{# Fail early if an unexpected value is provided -#}
{% set zodb_type = slapparameter_dict.get('zodb-software-type') -%}
{% set zodb_extern = slapparameter_dict.get('zodb-extern') -%}
{% if {'zeo': 1, None: 0}[zodb_type] -%}
{{ request('zodb', 'zodb-' ~ zodb_type, 'zodb', {'tcpv4-port': 2100, 'zodb-dict': {'root': {}}}, {'zodb-storage-type': False, 'zodb-dict': False, 'tidstorage-ip': False, 'tidstorage-port': False}) }}
{% else -%}
{% do zodb_extern[0] %}
{% endif -%}
[inituser-password]
{% set inituser_password = slapparameter_dict.get('inituser-password') -%}
{% if inituser_password -%}
passwd = {{ dumps(inituser_password) }}
{% else -%}
recipe = slapos.cookbook:generate.password
{% endif -%}
[deadlock-debugger-password]
{% set deadlock_debugger_password = slapparameter_dict.get('deadlock-debugger-password') -%}
{% if deadlock_debugger_password -%}
passwd = {{ dumps(deadlock_debugger_password) }}
{% else -%}
recipe = slapos.cookbook:generate.password
{% endif -%}
[request-zope-base]
< = request-common
return =
zope-address-list
hosts-dict
config-bt5 = {{ dumps(slapparameter_dict.get('bt5', 'erp5_full_text_myisam_catalog erp5_configurator_standard erp5_configurator_maxma_demo erp5_configurator_ung erp5_configurator_run_my_doc slapos_configurator')) }}
config-bt5-repository-url = {{ dumps(slapparameter_dict.get('bt5-repository-url', local_bt5_repository)) }}
config-cloudooo-url = ${request-cloudooo:connection-url}
config-deadlock-debugger-password = ${deadlock-debugger-password:passwd}
config-developer-list = {{ dumps(slapparameter_dict.get('developer-list', [inituser_login])) }}
config-hosts-dict = {{ dumps(slapparameter_dict.get('hosts-dict', {})) }}
config-inituser-login = {{ dumps(inituser_login) }}
config-inituser-password = ${inituser-password:passwd}
config-kumofs-url = ${request-memcached-persistent:connection-url}
config-memcached-url = ${request-memcached-volatile:connection-url}
config-mysql-test-url-list = ${request-mariadb:connection-test-database-list}
config-mysql-url-list = ${request-mariadb:connection-database-list}
config-site-id = {{ dumps(site_id) }}
config-smtp-url = {{ dumps(slapparameter_dict.get('smtp-url', 'smtp://localhost:25/')) }}
config-timezone = {{ dumps(slapparameter_dict.get('timezone', 'UTC')) }}
{% if zodb_type -%}
config-tidstorage-ip = ${request-zodb:connection-tidstorage-ip}
config-tidstorage-port = ${request-zodb:connection-tidstorage-port}
config-zodb-dict = ${request-zodb:connection-zodb-dict}
config-zodb-storage-type = ${request-zodb:connection-zodb-storage-type}
{% endif -%}
{% if zodb_extern -%}
config-zodb-extern = {{ dumps(zodb_extern) }}
{% endif -%}
software-type = zope
{% set zope_family_dict = {} -%}
{% set zope_backend_path_dict = {} -%}
{% set ssl_authentication_dict = {} -%}
{% for custom_name, zope_parameter_dict in slapparameter_dict.get('zope-partition-dict', {'1': {}}).items() -%}
{% set partition_name = 'zope-' ~ custom_name -%}
{% set section_name = 'request-' ~ partition_name -%}
{% set backend_path = zope_parameter_dict.get('backend-path', '/') % {'site-id': site_id} %}
{% do zope_family_dict.setdefault(zope_parameter_dict.get('family', 'default'), []).append(section_name) -%}
{% do zope_backend_path_dict.setdefault(zope_parameter_dict.get('family', 'default'), backend_path) -%}
{% do ssl_authentication_dict.setdefault(zope_parameter_dict.get('family', 'default'), zope_parameter_dict.get('ssl-authentication', False)) -%}
[{{ section_name }}]
< = request-zope-base
name = {{ partition_name }}
config-name = {{ dumps(custom_name) }}
config-instance-count = {{ dumps(zope_parameter_dict.get('instance-count', 1)) }}
config-thread-amount = {{ dumps(zope_parameter_dict.get('thread-amount', 1)) }}
config-timerserver-interval = {{ dumps(zope_parameter_dict.get('timerserver-interval', 5)) }}
config-longrequest-logger-interval = {{ dumps(zope_parameter_dict.get('longrequest-logger-interval', -1)) }}
config-longrequest-logger-timeout = {{ dumps(zope_parameter_dict.get('longrequest-logger-timeout', 1)) }}
config-port-base = {{ dumps(zope_parameter_dict.get('port-base', 2200)) }}
config-webdav = {{ dumps(zope_parameter_dict.get('webdav', False)) }}
sla-computer_guid = {{ dumps(zope_parameter_dict.get('computer-guid', computer_id)) }}
{% endfor -%}
{# We need to concatenate lists that we cannot read as lists, so this gets hairy. -#}
{% set zope_address_list_id_dict = {} -%}
{% set zope_family_parameter_dict = {} -%}
{% for family_name, zope_section_id_list in zope_family_dict.items() -%}
{% for zope_section_id in zope_section_id_list -%}
{% set parameter_name = 'zope-family-entry-' ~ zope_section_id -%}
{% do zope_address_list_id_dict.__setitem__(zope_section_id, parameter_name) -%}
{% do zope_family_parameter_dict.setdefault(family_name, []).append(parameter_name) -%}
{% endfor -%}
{% if has_frontend -%}
{% set frontend_name = 'frontend-' ~ family_name -%}
{% set publishable = frontend_name ~ ':connection-site_url' -%}
[{{ frontend_name }}]
< = request-frontend-base
name = {{ frontend_name }}
config-url = ${request-balancer:{{ family_name }}-v6}
{% else -%}
{% set publishable = 'request-balancer:connection-' ~ family_name -%}
{% endif -%}
{% do publish_dict.__setitem__('family-' ~ family_name, '${' ~ publishable ~ '}' ) -%}
{% endfor -%}
{% set balancer_dict = slapparameter_dict.get('balancer', {}) -%}
[request-balancer]
< = request-common
name = balancer
software-type = balancer
sla-computer_guid = {{ dumps(slapparameter_dict.get('balancer-computer-guid', computer_id)) }}
return =
{%- for family in zope_family_dict %}
{{ family }}
{{ family }}-v6
{% endfor -%}
config-zope-family-dict = {{ dumps(zope_family_parameter_dict) }}
config-backend-path-dict = {{ dumps(zope_backend_path_dict) }}
config-ssl-authentication-dict = {{ dumps(ssl_authentication_dict) }}
config-tcpv4-port = {{ dumps(balancer_dict.get('tcpv4-port', 2150)) }}
{% for zope_section_id, name in zope_address_list_id_dict.items() -%}
config-{{ name }} = {{ ' ${' ~ zope_section_id ~ ':connection-zope-address-list}' }}
{% endfor -%}
# XXX: should those really be same for all families ?
config-haproxy-server-check-path = {{ dumps(balancer_dict.get('haproxy-server-check-path', '/') % {'site-id': site_id}) }}
config-ssl = {{ dumps(balancer_dict.get('ssl', {})) }}
config-country-code = {{ slapparameter_dict.get('country-code', 'ZZ') }}
config-email = {{ slapparameter_dict.get('email', 'nobody@example.com') }}
config-state = {{ slapparameter_dict.get('state', "('State',)") }}
config-city = {{ slapparameter_dict.get('city', 'City') }}
config-company = {{ slapparameter_dict.get('company', 'Compagny') }}
[request-frontend-base]
{% if has_frontend -%}
< = request-common
software-url = {{ dumps(frontend_dict['software-url']) }}
software-type = {{ dumps(frontend_dict.get('software-type', 'RootSoftwareInstance')) }}
sla-instance_guid = {{ dumps(frontend_dict['instance-guid']) }}
slave = true
{% set config_dict = {
'type': 'zope',
} -%}
{% if frontend_dict.get('domain') -%}
{% do config_dict.__setitem__('custom_domain', frontend_dict['domain']) -%}
{% endif -%}
{% for name, value in config_dict.items() -%}
config-{{ name }} = {{ value }}
{% endfor -%}
return = site_url
{% endif -%}
[publish]
recipe = slapos.cookbook:publish.serialised
deadlock-debugger-password = ${deadlock-debugger-password:passwd}
inituser-password = ${inituser-password:passwd}
{#
Pick any published hosts-dict, they are expected to be identical - and there is
no way to check here.
-#}
hosts-dict = {{ '${' ~ zope_address_list_id_dict.keys()[0] ~ ':connection-hosts-dict}' }}
{% for name, value in publish_dict.items() -%}
{{ name }} = {{ value }}
{% endfor -%}
[buildout]
parts = publish
[buildout]
extends =
../../stack/erp5/buildout.cfg
parts +=
vifib-fix-products-paths
[local-bt5-repository]
# Same as bt5-repository, but only local repository.
# Used to generate bt5lists.
list = ${erp5:location}/bt5 ${erp5:location}/product/ERP5/bootstrap ${vifib:location}/master/bt5
[genbt5list]
recipe = plone.recipe.command
stop-on-error = true
genbt5list = ${erp5:location}/product/ERP5/bin/genbt5list
command =
${buildout:executable} ${:genbt5list} ${local-bt5-repository:list}
update-command = ${:command}
[erp5_repository_list]
repository_id_list = erp5 vifib/master
[erp5]
recipe = slapos.recipe.build:gitclone
repository = http://git.erp5.org/repos/erp5.git
branch = interaction-drop
git-executable = ${git:location}/bin/git
[vifib]
recipe = slapos.recipe.build:gitclone
repository = http://git.erp5.org/repos/slapos.core.git
branch = master
git-executable = ${git:location}/bin/git
[vifib-fix-products-paths]
recipe = plone.recipe.command
stop-on-error = true
command =
for DIR in "${vifib:location}/master"; do cd "$DIR"; rm -f Products ; ln -s product Products; touch product/__init__.py; done
update-command = ${:command}
[eggs]
eggs +=
suds
facebook-sdk
google-api-python-client
spyne
slapos.core
dummy +=
${vifib:location}
extra-paths +=
${vifib:location}/master
[template-erp5]
md5sum = 6ada1fd4af0a451516443bfb6d00b717
[template-balancer]
md5sum = 818ab59ae966114735866aecef7a8563
[template-apache-conf]
md5sum = bb329fc28bef095a01efc901d2f84149
[template-create-erp5-site-real]
md5sum = 61824aab2172d21f1d6403a35cab47cd
[versions]
python-memcached = 1.47
facebook-sdk = 0.4.0
google-api-python-client = 1.2
[networkcache]
# signature certificates of the following uploaders.
# Romain Courteaud
# Sebastien Robin
# Kazuhiko Shiozaki
# Cedric de Saint Martin
# Yingjie Xu
# Gabriel Monnerat
# Łukasz Nowak
# Test Agent (Automatic update from tests)
# Aurélien Calonne
signature-certificate-list =
-----BEGIN CERTIFICATE-----
MIIB4DCCAUkCADANBgkqhkiG9w0BAQsFADA5MQswCQYDVQQGEwJGUjEZMBcGA1UE
CBMQRGVmYXVsdCBQcm92aW5jZTEPMA0GA1UEChMGTmV4ZWRpMB4XDTExMDkxNTA5
MDAwMloXDTEyMDkxNTA5MDAwMlowOTELMAkGA1UEBhMCRlIxGTAXBgNVBAgTEERl
ZmF1bHQgUHJvdmluY2UxDzANBgNVBAoTBk5leGVkaTCBnzANBgkqhkiG9w0BAQEF
AAOBjQAwgYkCgYEApYZv6OstoqNzxG1KI6iE5U4Ts2Xx9lgLeUGAMyfJLyMmRLhw
boKOyJ9Xke4dncoBAyNPokUR6iWOcnPHtMvNOsBFZ2f7VA28em3+E1JRYdeNUEtX
Z0s3HjcouaNAnPfjFTXHYj4um1wOw2cURSPuU5dpzKBbV+/QCb5DLheynisCAwEA
ATANBgkqhkiG9w0BAQsFAAOBgQBCZLbTVdrw3RZlVVMFezSHrhBYKAukTwZrNmJX
mHqi2tN8tNo6FX+wmxUUAf3e8R2Ymbdbn2bfbPpcKQ2fG7PuKGvhwMG3BlF9paEC
q7jdfWO18Zp/BG7tagz0jmmC4y/8akzHsVlruo2+2du2freE8dK746uoMlXlP93g
QUUGLQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB8jCCAVugAwIBAgIJAPu2zchZ2BxoMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV
BAMMB3RzeGRldjMwHhcNMTExMDE0MTIxNjIzWhcNMTIxMDEzMTIxNjIzWjASMRAw
DgYDVQQDDAd0c3hkZXYzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrPbh+
YGmo6mWmhVb1vTqX0BbeU0jCTB8TK3i6ep3tzSw2rkUGSx3niXn9LNTFNcIn3MZN
XHqbb4AS2Zxyk/2tr3939qqOrS4YRCtXBwTCuFY6r+a7pZsjiTNddPsEhuj4lEnR
L8Ax5mmzoi9nE+hiPSwqjRwWRU1+182rzXmN4QIDAQABo1AwTjAdBgNVHQ4EFgQU
/4XXREzqBbBNJvX5gU8tLWxZaeQwHwYDVR0jBBgwFoAU/4XXREzqBbBNJvX5gU8t
LWxZaeQwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA07q/rKoE7fAda
FED57/SR00OvY9wLlFEF2QJ5OLu+O33YUXDDbGpfUSF9R8l0g9dix1JbWK9nQ6Yd
R/KCo6D0sw0ZgeQv1aUXbl/xJ9k4jlTxmWbPeiiPZEqU1W9wN5lkGuLxV4CEGTKU
hJA/yXa1wbwIPGvX3tVKdOEWPRXZLg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB7jCCAVegAwIBAgIJAJWA0jQ4o9DGMA0GCSqGSIb3DQEBBQUAMA8xDTALBgNV
BAMMBHg2MXMwIBcNMTExMTI0MTAyNDQzWhgPMjExMTEwMzExMDI0NDNaMA8xDTAL
BgNVBAMMBHg2MXMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANdJNiFsRlkH
vq2kHP2zdxEyzPAWZH3CQ3Myb3F8hERXTIFSUqntPXDKXDb7Y/laqjMXdj+vptKk
3Q36J+8VnJbSwjGwmEG6tym9qMSGIPPNw1JXY1R29eF3o4aj21o7DHAkhuNc5Tso
67fUSKgvyVnyH4G6ShQUAtghPaAwS0KvAgMBAAGjUDBOMB0GA1UdDgQWBBSjxFUE
RfnTvABRLAa34Ytkhz5vPzAfBgNVHSMEGDAWgBSjxFUERfnTvABRLAa34Ytkhz5v
PzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFLDS7zNhlrQYSQO5KIj
z2RJe3fj4rLPklo3TmP5KLvendG+LErE2cbKPqnhQ2oVoj6u9tWVwo/g03PMrrnL
KrDm39slYD/1KoE5kB4l/p6KVOdeJ4I6xcgu9rnkqqHzDwI4v7e8/D3WZbpiFUsY
vaZhjNYKWQf79l6zXfOvphzJ
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAO4V/jiMoICoMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtMjMyMCAXDTEyMDIxNjExMTAyM1oYDzIxMTIwMTIzMTExMDIzWjAT
MREwDwYDVQQDDAhDT01QLTIzMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
wi/3Z8W9pUiegUXIk/AiFDQ0UJ4JFAwjqr+HSRUirlUsHHT+8DzH/hfcTDX1I5BB
D1ADk+ydXjMm3OZrQcXjn29OUfM5C+g+oqeMnYQImN0DDQIOcUyr7AJc4xhvuXQ1
P2pJ5NOd3tbd0kexETa1LVhR6EgBC25LyRBRae76qosCAwEAAaNQME4wHQYDVR0O
BBYEFMDmW9aFy1sKTfCpcRkYnP6zUd1cMB8GA1UdIwQYMBaAFMDmW9aFy1sKTfCp
cRkYnP6zUd1cMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAskbFizHr
b6d3iIyN+wffxz/V9epbKIZVEGJd/6LrTdLiUfJPec7FaxVCWNyKBlCpINBM7cEV
Gn9t8mdVQflNqOlAMkOlUv1ZugCt9rXYQOV7rrEYJBWirn43BOMn9Flp2nibblby
If1a2ZoqHRxoNo2yTmm7TSYRORWVS+vvfjY=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAIlBksrZVkK8MA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtMzU3MCAXDTEyMDEyNjEwNTUyOFoYDzIxMTIwMTAyMTA1NTI4WjAT
MREwDwYDVQQDDAhDT01QLTM1NzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
ts+iGUwi44vtIfwXR8DCnLtHV4ydl0YTK2joJflj0/Ws7mz5BYkxIU4fea/6+VF3
i11nwBgYgxQyjNztgc9u9O71k1W5tU95yO7U7bFdYd5uxYA9/22fjObaTQoC4Nc9
mTu6r/VHyJ1yRsunBZXvnk/XaKp7gGE9vNEyJvPn2bkCAwEAAaNQME4wHQYDVR0O
BBYEFKuGIYu8+6aEkTVg62BRYaD11PILMB8GA1UdIwQYMBaAFKuGIYu8+6aEkTVg
62BRYaD11PILMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAMoTRpBxK
YLEZJbofF7gSrRIcrlUJYXfTfw1QUBOKkGFFDsiJpEg4y5pUk1s5Jq9K3SDzNq/W
it1oYjOhuGg3al8OOeKFrU6nvNTF1BAvJCl0tr3POai5yXyN5jlK/zPfypmQYxE+
TaqQSGBJPVXYt6lrq/PRD9ciZgKLOwEqK8w=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAPHoWu90gbsgMA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMMCXZpZmlibm9kZTAeFw0xMjAzMTkyMzIwNTVaFw0xMzAzMTkyMzIwNTVaMBQx
EjAQBgNVBAMMCXZpZmlibm9kZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
ozBijpO8PS5RTeKTzA90vi9ezvv4vVjNaguqT4UwP9+O1+i6yq1Y2W5zZxw/Klbn
oudyNzie3/wqs9VfPmcyU9ajFzBv/Tobm3obmOqBN0GSYs5fyGw+O9G3//6ZEhf0
NinwdKmrRX+d0P5bHewadZWIvlmOupcnVJmkks852BECAwEAAaNQME4wHQYDVR0O
BBYEFF9EtgfZZs8L2ZxBJxSiY6eTsTEwMB8GA1UdIwQYMBaAFF9EtgfZZs8L2ZxB
JxSiY6eTsTEwMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAc43YTfc6
baSemaMAc/jz8LNLhRE5dLfLOcRSoHda8y0lOrfe4lHT6yP5l8uyWAzLW+g6s3DA
Yme/bhX0g51BmI6gjKJo5DoPtiXk/Y9lxwD3p7PWi+RhN+AZQ5rpo8UfwnnN059n
yDuimQfvJjBFMVrdn9iP6SfMjxKaGk6gVmI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAMNZBmoIOXPBMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtMTMyMCAXDTEyMDUwMjEyMDQyNloYDzIxMTIwNDA4MTIwNDI2WjAT
MREwDwYDVQQDDAhDT01QLTEzMjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
6peZQt1sAmMAmSG9BVxxcXm8x15kE9iAplmANYNQ7z2YO57c10jDtlYlwVfi/rct
xNUOKQtc8UQtV/fJWP0QT0GITdRz5X/TkWiojiFgkopza9/b1hXs5rltYByUGLhg
7JZ9dZGBihzPfn6U8ESAKiJzQP8Hyz/o81FPfuHCftsCAwEAAaNQME4wHQYDVR0O
BBYEFNuxsc77Z6/JSKPoyloHNm9zF9yqMB8GA1UdIwQYMBaAFNuxsc77Z6/JSKPo
yloHNm9zF9yqMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAl4hBaJy1
cgiNV2+Z5oNTrHgmzWvSY4duECOTBxeuIOnhql3vLlaQmo0p8Z4c13kTZq2s3nhd
Loe5mIHsjRVKvzB6SvIaFUYq/EzmHnqNdpIGkT/Mj7r/iUs61btTcGUCLsUiUeci
Vd0Ozh79JSRpkrdI8R/NRQ2XPHAo+29TT70=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB9jCCAV+gAwIBAgIJAKRvzcy7OH0UMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
BAMMCENPTVAtNzcyMCAXDTEyMDgxMDE1NDI1MVoYDzIxMTIwNzE3MTU0MjUxWjAT
MREwDwYDVQQDDAhDT01QLTc3MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
o7aipd6MbnuGDeR1UJUjuMLQUariAyQ2l2ZDS6TfOwjHiPw/mhzkielgk73kqN7A
sUREx41eTcYCXzTq3WP3xCLE4LxLg1eIhd4nwNHj8H18xR9aP0AGjo4UFl5BOMa1
mwoyBt3VtfGtUmb8whpeJgHhqrPPxLoON+i6fIbXDaUCAwEAAaNQME4wHQYDVR0O
BBYEFEfjy3OopT2lOksKmKBNHTJE2hFlMB8GA1UdIwQYMBaAFEfjy3OopT2lOksK
mKBNHTJE2hFlMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAaNRx6YN2
M/p3R8/xS6zvH1EqJ3FFD7XeAQ52WuQnKSREzuw0dsw12ClxjcHiQEFioyTiTtjs
5pW18Ry5Ie7iFK4cQMerZwWPxBodEbAteYlRsI6kePV7Gf735Y1RpuN8qZ2sYL6e
x2IMeSwJ82BpdEI5niXxB+iT0HxhmR+XaMI=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB+DCCAWGgAwIBAgIJAKGd0vpks6T/MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMMCUNPTVAtMTU4NDAgFw0xMzA2MjAxMjE5MjBaGA8yMTEzMDUyNzEyMTkyMFow
FDESMBAGA1UEAwwJQ09NUC0xNTg0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDZTH9etPUC+wMZQ3UIiOwyyCfHsJ+7duCFYjuo1uZrhtDt/fp8qb8qK9ob+df3
EEYgA0IgI2j/9jNUEnKbc5+OrfKznzXjrlrH7zU8lKBVNCLzQuqBKRNajZ+UvO8R
nlqK2jZCXP/p3HXDYUTEwIR5W3tVCEn/Vda4upTLcPVE5wIDAQABo1AwTjAdBgNV
HQ4EFgQU7KXaNDheQWoy5uOU01tn1M5vNkEwHwYDVR0jBBgwFoAU7KXaNDheQWoy
5uOU01tn1M5vNkEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQASmqCU
Znbvu6izdicvjuE3aKnBa7G++Fdp2bdne5VCwVbVLYCQWatB+n4crKqGdnVply/u
+uZ16u1DbO9rYoKgWqjLk1GfiLw5v86pd5+wZd5I9QJ0/Sbz2vZk5S4ciMIGwArc
m711+GzlW5xe6GyH9SZaGOPAdUbI6JTDwLzEgA==
-----END CERTIFICATE-----
...@@ -7,7 +7,11 @@ parts -= wendelin.core ...@@ -7,7 +7,11 @@ parts -= wendelin.core
parts += wendelin.core-dev parts += wendelin.core-dev
# also tell erp5 to use -dev eggs instead of released ones
[eggs] [eggs]
# tell erp5 to use -dev eggs instead of released ones
eggs -= ${wendelin.core:egg} eggs -= ${wendelin.core:egg}
eggs += ${wendelin.core-dev:egg} eggs += ${wendelin.core-dev:egg}
# kill -USR1 <runzope-pid> -> traceback of all threads -> stdout
# ( logged to slappartX/.slappartX_zope-Y.log )
Products.signalstack
(in no special order)
General:
- ipv6 support (besides frontend-backend apache connection)
requires important changes at ERP5 level
- resilience
- make mariadb user accounts accept connections only from relevant IPs
or make x509 mandatory (needs ZMySQLD*A support)
- postfix
Monitoring:
- daily slow-query digest
make percona toolkit available in mysql instance and decide how to send digest
- daily apachedex
Backups:
- flush binlogs independently from full backups (in addition to anyway flushing them on full backup creation)
- rotate tidstorage consistency points
- make mysql backup path an instance parameter
- make srv/backup/zodb the default value for a parameter (zodb{ 'backup_root': ...} or so) to have a single value to modify to relocate zodb backups of a partition
- make srv/backup/logrotate customisable (per partition, otherwise files will overwrite each other)
LoadModule unixd_module modules/mod_unixd.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule headers_module modules/mod_headers.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.so
AddOutputFilterByType DEFLATE text/cache-manifest text/html text/plain text/css application/hal+json application/json application/x-javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml
PidFile "{{ parameter_dict['pid-file'] }}"
ServerAdmin admin@
TypesConfig conf/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
ServerTokens Prod
ServerSignature Off
TraceEnable Off
TimeOut {{ parameter_dict['timeout'] }}
SSLCertificateFile {{ parameter_dict['cert'] }}
SSLCertificateKeyFile {{ parameter_dict['key'] }}
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
SSLProtocol All -SSLv2
#SSLHonorCipherOrder on
{% if parameter_dict['cipher'] -%}
SSLCipherSuite {{ parameter_dict['cipher'] }}
{%- endif %}
SSLSessionCache shmcb:{{ parameter_dict['ssl-session-cache'] }}(512000)
SSLProxyEngine On
# As backend is trusting REMOTE_USER header unset it always
RequestHeader unset REMOTE_USER
{% if parameter_dict['ca-cert'] -%}
SSLVerifyClient require
RequestHeader set REMOTE_USER %{SSL_CLIENT_S_DN_CN}s
SSLCACertificateFile {{ parameter_dict['ca-cert'] }}
SSLCARevocationCheck chain
SSLCARevocationFile {{ parameter_dict['crl'] }}
{%- endif %}
ErrorLog "{{ parameter_dict['error-log'] }}"
# Default apache log format with request time in microsecond at the end
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %D" combined
CustomLog "{{ parameter_dict['access-log'] }}" combined
<Directory />
Options FollowSymLinks
AllowOverride None
Allow from all
</Directory>
RewriteEngine On
{% for port, _, backend in parameter_dict['backend-list'] -%}
{% for ip in parameter_dict['ip-list'] -%}
Listen {{ ip }}:{{ port }}
{% endfor -%}
<VirtualHost *:{{ port }}>
SSLEngine on
RewriteRule ^/(.*) {{ backend }}/$1 [L,P]
</VirtualHost>
{% endfor -%}
...@@ -5,11 +5,8 @@ find-links += ...@@ -5,11 +5,8 @@ find-links +=
extends = extends =
# Exact version of Zope # Exact version of Zope
https://raw.github.com/zopefoundation/Zope/2.13.22/versions.cfg https://raw.github.com/zopefoundation/Zope/2.13.22/versions.cfg
../../stack/slapos.cfg
../../component/logrotate/buildout.cfg
../../component/cups/buildout.cfg ../../component/cups/buildout.cfg
../../component/dbus/buildout.cfg ../../component/dbus/buildout.cfg
../../component/dcron/buildout.cfg
../../component/file/buildout.cfg ../../component/file/buildout.cfg
../../component/fonts/buildout.cfg ../../component/fonts/buildout.cfg
../../component/ghostscript/buildout.cfg ../../component/ghostscript/buildout.cfg
...@@ -27,28 +24,22 @@ extends = ...@@ -27,28 +24,22 @@ extends =
../../component/libffi/buildout.cfg ../../component/libffi/buildout.cfg
../../component/libpng/buildout.cfg ../../component/libpng/buildout.cfg
../../component/libreoffice-bin/buildout.cfg ../../component/libreoffice-bin/buildout.cfg
../../component/lxml-python/buildout.cfg
../../component/mesa/buildout.cfg ../../component/mesa/buildout.cfg
../../component/numpy/buildout.cfg ../../component/numpy/buildout.cfg
../../component/percona-toolkit/buildout.cfg ../../component/percona-toolkit/buildout.cfg
../../component/mariadb/buildout.cfg
../../component/mysql-python/buildout.cfg
../../component/patch/buildout.cfg ../../component/patch/buildout.cfg
../../component/pillow/buildout.cfg ../../component/pillow/buildout.cfg
../../component/pycrypto-python/buildout.cfg ../../component/pycrypto-python/buildout.cfg
../../component/pysvn-python/buildout.cfg ../../component/pysvn-python/buildout.cfg
../../component/python-2.7/buildout.cfg
../../component/python-ldap-python/buildout.cfg ../../component/python-ldap-python/buildout.cfg
../../component/rdiff-backup/buildout.cfg ../../component/rdiff-backup/buildout.cfg
../../component/stunnel/buildout.cfg ../../component/stunnel/buildout.cfg
../../component/subversion/buildout.cfg ../../component/subversion/buildout.cfg
../../component/tesseract/buildout.cfg ../../component/tesseract/buildout.cfg
../../component/varnish/buildout.cfg
../../component/w3-validator/buildout.cfg ../../component/w3-validator/buildout.cfg
../../component/w3m/buildout.cfg ../../component/w3m/buildout.cfg
../../component/xorg/buildout.cfg ../../component/xorg/buildout.cfg
../../component/poppler/buildout.cfg ../../component/poppler/buildout.cfg
../../component/xtrabackup/buildout.cfg
../../component/zabbix/buildout.cfg ../../component/zabbix/buildout.cfg
../../component/sed/buildout.cfg ../../component/sed/buildout.cfg
../../component/coreutils/buildout.cfg ../../component/coreutils/buildout.cfg
...@@ -58,8 +49,12 @@ extends = ...@@ -58,8 +49,12 @@ extends =
../../component/aspell/buildout.cfg ../../component/aspell/buildout.cfg
../../component/cloudooo/buildout.cfg ../../component/cloudooo/buildout.cfg
../../component/jsl/buildout.cfg ../../component/jsl/buildout.cfg
../../component/6tunnel/buildout.cfg
../../component/findutils/buildout.cfg
../../component/userhosts/buildout.cfg
../../software/neoppod/software-common.cfg
parts = parts +=
erp5-util-develop erp5-util-develop
slapos-cookbook-develop slapos-cookbook-develop
slapos-cookbook slapos-cookbook
...@@ -74,12 +69,10 @@ parts = ...@@ -74,12 +69,10 @@ parts =
haproxy haproxy
jsl jsl
stunnel stunnel
varnish-3.0
w3m w3m
poppler poppler
libpng libpng
ghostscript ghostscript
mariadb
mroonga-mariadb mroonga-mariadb
imagemagick imagemagick
inkscape inkscape
...@@ -94,9 +87,9 @@ parts = ...@@ -94,9 +87,9 @@ parts =
perl-DBI perl-DBI
percona-toolkit percona-toolkit
zabbix-agent zabbix-agent
dcron
dash dash
wget wget
userhosts
# Buildoutish # Buildoutish
eggs eggs
...@@ -132,77 +125,91 @@ parts = ...@@ -132,77 +125,91 @@ parts =
# Create instance template # Create instance template
template template
[template-jinja2-base] [download-base]
recipe = slapos.recipe.template:jinja2 <= download-base-neo
mode = 640 url = ${:_profile_base_location_}/${:filename}
template = ${:_profile_base_location_}/${:filename}.in
rendered = ${buildout:directory}/${:filename} [check-recipe]
# XXX: extra-context is needed because we cannot append to a key of an extended recipe = plone.recipe.command
# section. stop-on-error = true
extra-context = update-command = ${:command}
context = command = grep parts ${buildout:develop-eggs-directory}/slapos.cookbook.egg-link
key bin_directory buildout:bin-directory
key develop_eggs_directory buildout:develop-eggs-directory
key eggs_directory buildout:eggs-directory
key slapos_core_version versions:slapos.core
${:extra-context}
[mariadb-resiliency-after-import-script] [mariadb-resiliency-after-import-script]
recipe = slapos.recipe.build:download recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/template/instance-mariadb-resiliency-after-import-script.sh.in url = ${:_profile_base_location_}/template/instance-mariadb-resiliency-after-import-script.sh.in
md5sum = a9851920bb22ae58c2eb9dc3e955250c md5sum = b32d9ee1cb85f85d8d2f2b58f58459f1
mode = 755 mode = 755
[template-mariadb] [template-mariadb]
recipe = slapos.recipe.build:download <= download-base
url = ${:_profile_base_location_}/instance-mariadb.cfg.in filename = instance-mariadb.cfg.in
md5sum = a5f9888bd882331c35d48f05e468a0a2 md5sum = 4d46ab5aa651a39c4021de6f647e8be9
mode = 640 link-binary =
${coreutils:location}/bin/basename
[template-zope] ${coreutils:location}/bin/cat
recipe = slapos.recipe.build:download ${coreutils:location}/bin/cp
url = ${:_profile_base_location_}/instance-zope.cfg.in ${coreutils:location}/bin/ls
md5sum = ddf63b8dac634df63133c24f36df1050 ${coreutils:location}/bin/tr
mode = 640 ${coreutils:location}/bin/uname
${gettext:location}/lib/gettext/hostname
${grep:location}/bin/grep
${sed:location}/bin/sed
${mariadb:location}/bin/mysqlbinlog
[template-kumofs] [template-kumofs]
< = template-jinja2-base <= download-base
filename = instance-kumofs.cfg filename = instance-kumofs.cfg.in
md5sum = 627369560a030b006dbdd8f10ff6694a md5sum = 7d9760fe65f454700342eeffec14c884
extra-context =
key dash_location dash:location
key dcron_location dcron:location
key gzip_location gzip:location
key kumo_location kumo:location
key logrotate_location logrotate:location
[template-tidstorage]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/instance-tidstorage.cfg.in
md5sum = 20ee9db93c57425319cd4b385d327d39
mode = 640
[template-cloudooo] [template-cloudooo]
recipe = slapos.recipe.build:download <= download-base
url = ${:_profile_base_location_}/instance-cloudoo.cfg.in filename = instance-cloudoo.cfg.in
md5sum = 79eb68a9c5073535e8a98897385828a8 md5sum = 050fa6ff4eb397c5d4cb41a9f75afb3f
mode = 640
[template-zope-conf] [template-zope-conf]
recipe = slapos.recipe.build:download <= download-base
url = ${:_profile_base_location_}/zope.conf.in filename = zope.conf.in
md5sum = bc2154161a1d5baddc4ed4dfaaf94fbe md5sum = 0bf51218ecbf2bd319214192448a3ef7
mode = 640
[template-runzope-userhosts-preloaded]
<= download-base
filename = runzope_userhosts_preloaded.in
md5sum = bc6048b85b410693e60e5a77399dd1b7
[template-my-cnf]
<= download-base
filename = my.cnf.in
md5sum = dd779e54d22105702aa72cadc994d957
[template-mariadb-initial-setup]
<= download-base
filename = mariadb_initial_setup.sql.in
md5sum = b8d2d9af0c4cab45c8337aeac28d5fae
[template-create-erp5-site]
<= download-base
filename = instance-create-erp5-site.cfg.in
md5sum = 408fd955a876a1004ed35f578029a7d2
[template-create-erp5-site-real]
<= download-base
filename = instance-create-erp5-site-real.cfg.in
md5sum = e40e2e39f4941c6372f4357e8589a5cf
[template] [template]
< = template-jinja2-base recipe = slapos.recipe.template:jinja2
# XXX: "template.cfg" is hardcoded in instanciation recipe # XXX: "template.cfg" is hardcoded in instanciation recipe
filename = template.cfg rendered = ${buildout:directory}/template.cfg
template = ${:_profile_base_location_}/instance.cfg.in template = ${:_profile_base_location_}/instance.cfg.in
md5sum = 38d87bbb2b8193eb588b05ae6b8bbb3d md5sum = 6a2c99f8df8bb8fe8e2b7fa96f68f62b
extra-context = mode = 640
context =
key mariadb_link_binary template-mariadb:link-binary
key zope_link_binary template-zope:link-binary
key apache_location apache:location key apache_location apache:location
key aspell_location aspell:location key aspell_location aspell:location
key bin_directory buildout:bin-directory
key buildout_bin_directory buildout:bin-directory key buildout_bin_directory buildout:bin-directory
key coreutils_location coreutils:location key coreutils_location coreutils:location
key cups_location cups:location key cups_location cups:location
...@@ -211,23 +218,19 @@ extra-context = ...@@ -211,23 +218,19 @@ extra-context =
key dbus_glib_location dbus-glib:location key dbus_glib_location dbus-glib:location
key dbus_location dbus:location key dbus_location dbus:location
key dcron_location dcron:location key dcron_location dcron:location
key dmtx_utils_location dmtx-utils:location
key erp5_location erp5:location key erp5_location erp5:location
key file_location file:location key file_location file:location
key findutils_location findutils:location key findutils_location findutils:location
key fontconfig_location fontconfig:location key fontconfig_location fontconfig:location
key fonts_location fonts:location key fonts_location fonts:location
key freetype_location freetype:location key freetype_location freetype:location
key gettext_location gettext:location
key git_location git:location
key glib_location glib:location key glib_location glib:location
key glu_location glu:location key glu_location glu:location
key graphviz_location graphviz:location
key grep_location grep:location
key gzip_location gzip:location key gzip_location gzip:location
key haproxy_location haproxy:location key haproxy_location haproxy:location
key imagemagick_location imagemagick:location key instance_common_cfg instance-common:rendered
key jsl_location jsl:location key jsl_location jsl:location
key kumo_location kumo:location
key libICE_location libICE:location key libICE_location libICE:location
key libSM_location libSM:location key libSM_location libSM:location
key libX11_location libX11:location key libX11_location libX11:location
...@@ -242,64 +245,84 @@ extra-context = ...@@ -242,64 +245,84 @@ extra-context =
key librsvg_location librsvg:location key librsvg_location librsvg:location
key libxcb_location libxcb:location key libxcb_location libxcb:location
key local_bt5_repository local-bt5-repository:list key local_bt5_repository local-bt5-repository:list
key bt5_list local-bt5-repository:bt5_list
key logrotate_location logrotate:location key logrotate_location logrotate:location
key mariadb_location mariadb:location key mariadb_location mariadb:location
key mariadb_resiliency_after_import_script mariadb-resiliency-after-import-script:target key mariadb_resiliency_after_import_script mariadb-resiliency-after-import-script:target
key mesa_location mesa:location key mesa_location mesa:location
key openssl_location openssl:location key openssl_location openssl:location
key perl_location perl:location key root_common root-common:target
key perl_siteprefix perl:siteprefix key sixtunnel_location 6tunnel:location
key poppler_location poppler:location key slapos_core_version versions:slapos.core
key sed_location sed:location
key stunnel_location stunnel:location key stunnel_location stunnel:location
key template_apache_conf template-apache-conf:target
key template_balancer template-balancer:target
key template_cloudooo template-cloudooo:target key template_cloudooo template-cloudooo:target
key template_erp5_cluster template-erp5-cluster:target key template_create_erp5_site template-create-erp5-site:target
key template_erp5_single template-erp5-single:target key template_create_erp5_site_real template-create-erp5-site-real:target
key template_kumofs template-kumofs:rendered key template_erp5 template-erp5:target
key template_haproxy_cfg template-haproxy-cfg:target
key template_kumofs template-kumofs:target
key template_mariadb template-mariadb:target key template_mariadb template-mariadb:target
key template_memcached template-memcached:rendered key template_mariadb_initial_setup template-mariadb-initial-setup:target
key template_tidstorage template-tidstorage:target key template_my_cnf template-my-cnf:target
key template_varnish template-varnish:target key template_runzope_userhosts_preloaded template-runzope-userhosts-preloaded:target
key template_zeo template-zeo:target
key template_zope template-zope:target key template_zope template-zope:target
key template_zope_conf template-zope-conf:target key template_zope_conf template-zope-conf:target
key tesseract_location tesseract:location key userhosts_location userhosts:location
key varnish_location varnish-3.0:location
key w3m_location w3m:location
key wget_location wget:location key wget_location wget:location
key xdamage_location xdamage:location key xdamage_location xdamage:location
key xfixes_location xfixes:location key xfixes_location xfixes:location
key xtrabackup_location xtrabackup:location
key zlib_location zlib:location key zlib_location zlib:location
[template-memcached] [template-erp5]
< = template-jinja2-base <= download-base
filename = instance-memcached.cfg filename = instance-erp5.cfg.in
md5sum = de63a79e6812854c44e961f5ac3b465d md5sum = 70820c1608edfc923d57ec2d92aed012
extra-context =
key dash_location dash:location
key dcron_location dcron:location
key gzip_location gzip:location
key kumo_location kumo:location
key logrotate_location logrotate:location
[template-erp5-single]
recipe = slapos.recipe.build:download
url = ${:_profile_base_location_}/instance-erp5-single.cfg.in
md5sum = 6dd76b8543347a11ebddcdc16dd98dd9
mode = 640
[template-erp5-cluster] [template-zeo]
recipe = slapos.recipe.build:download <= download-base
url = ${:_profile_base_location_}/instance-erp5-cluster.cfg.in filename = instance-zeo.cfg.in
md5sum = 5080559723859b40a390d700431ffedd md5sum = 9670cf63099e2c520017a23defff51a4
mode = 640
[template-varnish] [template-zope]
recipe = slapos.recipe.build:download <= download-base
url = ${:_profile_base_location_}/instance-varnish.cfg.in filename = instance-zope.cfg.in
md5sum = 98158d0b349e3579a20ab520dfa9ebb7 md5sum = 74f2fbd7d653b0e6cfe29efcd1042ace
mode = 640 link-binary =
${aspell:location}/bin/aspell
${dmtx-utils:location}/bin/dmtxwrite
${git:location}/bin/git
${graphviz:location}/bin/dot
${grep:location}/bin/grep
${imagemagick:location}/bin/convert
${imagemagick:location}/bin/identify
${jsl:location}/bin/jsl
${librsvg:location}/bin/rsvg-convert
${mariadb:location}/bin/mysql
${mariadb:location}/bin/mysqldump
${openssl:location}/bin/openssl
${poppler:location}/bin/pdfinfo
${poppler:location}/bin/pdftohtml
${poppler:location}/bin/pdftotext
${sed:location}/bin/sed
${tesseract:location}/bin/tesseract
${w3m:location}/bin/w3m
[template-balancer]
<= download-base
filename = instance-balancer.cfg.in
md5sum = 3628f0ba358e7ee96a8d0185c4775911
[template-apache-conf]
<= download-base
filename = apache.conf.in
md5sum = 713b22938d7212c8506449bc0508452b
[template-haproxy-cfg]
<= download-base
filename = haproxy.cfg.in
md5sum = 7f13123698afe017dfcde9de6beea0f5
[bt5-repository] [bt5-repository]
# Format: # Format:
...@@ -313,7 +336,6 @@ list = ${local-bt5-repository:list} ...@@ -313,7 +336,6 @@ list = ${local-bt5-repository:list}
# Same as bt5-repository, but only local repository. # Same as bt5-repository, but only local repository.
# Used to generate bt5lists. # Used to generate bt5lists.
list = ${erp5:location}/bt5 ${erp5:location}/product/ERP5/bootstrap list = ${erp5:location}/bt5 ${erp5:location}/product/ERP5/bootstrap
bt5_list = erp5_full_text_myisam_catalog erp5_configurator_standard erp5_configurator_maxma_demo erp5_configurator_ung erp5_configurator_run_my_doc erp5_configurator_ebusiness_lotse
[genbt5list] [genbt5list]
recipe = plone.recipe.command recipe = plone.recipe.command
...@@ -390,7 +412,7 @@ initialization = ...@@ -390,7 +412,7 @@ initialization =
sys.path[0:0] = ['/'.join(['''${buildout:parts-directory}''', x]) for x in repository_id_list] sys.path[0:0] = ['/'.join(['''${buildout:parts-directory}''', x]) for x in repository_id_list]
[eggs] [eggs]
recipe = zc.recipe.egg <= neoppod
eggs = eggs =
${numpy:egg} ${numpy:egg}
${mysql-python:egg} ${mysql-python:egg}
...@@ -439,9 +461,12 @@ eggs = ...@@ -439,9 +461,12 @@ eggs =
suds suds
pprofile pprofile
pycountry pycountry
xfw
jsonschema
# Needed for checking ZODB Components source code # Needed for checking ZODB Components source code
pylint pylint
neoppod[client]
# Zope # Zope
ZODB3 ZODB3
Zope2 Zope2
...@@ -503,8 +528,6 @@ Acquisition-patches = ${:_profile_base_location_}/../../component/egg-patch/Acqu ...@@ -503,8 +528,6 @@ Acquisition-patches = ${:_profile_base_location_}/../../component/egg-patch/Acqu
Acquisition-patch-options = -p1 Acquisition-patch-options = -p1
Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method.patch Products.DCWorkflow-patches = ${:_profile_base_location_}/../../component/egg-patch/Products.DCWorkflow/workflow_method.patch
Products.DCWorkflow-patch-options = -p1 Products.DCWorkflow-patch-options = -p1
ZODB3-patches = ${:_profile_base_location_}/../../component/egg-patch/ZODB3-3.10.5.patch
ZODB3-patch-options = -p1
[zodbanalyze] [zodbanalyze]
recipe = zc.recipe.egg recipe = zc.recipe.egg
...@@ -524,9 +547,6 @@ setup = ${erp5:location} ...@@ -524,9 +547,6 @@ setup = ${erp5:location}
branch = branch =
revision = 3241978a6ec832f6aa71d1df1a62e22a8feae2f1 revision = 3241978a6ec832f6aa71d1df1a62e22a8feae2f1
[slapos.cookbook-repository]
branch = erp5
[slapos-toolbox] [slapos-toolbox]
recipe = zc.recipe.egg recipe = zc.recipe.egg
eggs = eggs =
...@@ -535,15 +555,15 @@ eggs = ...@@ -535,15 +555,15 @@ eggs =
slapos.toolbox[zodbpack] slapos.toolbox[zodbpack]
scripts = scripts =
killpidfromfile is-local-tcp-port-opened
onetimedownload onetimedownload
slapos-kill
zodbpack zodbpack
[versions] [versions]
# patched eggs # patched eggs
Acquisition = 2.13.8+SlapOSPatched001 Acquisition = 2.13.8+SlapOSPatched001
Products.DCWorkflow = 2.2.4+SlapOSPatched001 Products.DCWorkflow = 2.2.4+SlapOSPatched001
ZODB3 = 3.10.5+SlapOSPatched001
# specify dev version to be sure that an old released version is not used # specify dev version to be sure that an old released version is not used
cloudooo = 1.2.5-dev cloudooo = 1.2.5-dev
......
{% set server_check_path = parameter_dict['server-check-path'] -%}
global
maxconn 4096
stats socket {{ parameter_dict['socket-path'] }} level admin
defaults
log global
mode http
option httplog
option dontlognull
retries 1
option redispatch
maxconn 2000
cookie SERVERID rewrite
http-send-name-header X-Balancer-Current-Server
balance roundrobin
stats uri /haproxy
stats realm Global\ statistics
# it is useless to have timeout much bigger than the one of apache.
# By default apache use 300s, so we set slightly more in order to
# make sure that apache will first stop the connection.
timeout server 305s
# Stop waiting in queue for a zope to become available.
# If no zope can be reached after one minute, consider the request will
# never succeed.
timeout queue 60s
# The connection should be immediate on LAN,
# so we should not set more than 5 seconds, and it could be already too much
timeout connect 5s
# As requested in haproxy doc, make this "at least equal to timeout server".
timeout client 305s
# Use "option forceclose" to not preserve client & server persistent connections
# while handling every incoming request individually, dispatching them one after
# another to servers, in HTTP close mode. This is really needed when haproxy
# is configured with maxconn to 1, without this option browsers are unable
# to render a page
option forceclose
{% for name, (port, backend_list) in parameter_dict['backend-dict'].items() -%}
listen {{ name }} {{ parameter_dict['ip'] }}:{{ port }}
http-request set-header X-Balancer-Current-Cookie SERVERID
{% set has_webdav = [] -%}
{% for address, connection_count, webdav in backend_list -%}
{% if webdav %}{% do has_webdav.append(None) %}{% endif -%}
{% set server_name = name ~ '-' ~ loop.index0 -%}
server {{ server_name }} {{ address }} cookie {{ server_name }} check inter 3s rise 1 fall 2 maxqueue 5 maxconn {{ connection_count }}
{% endfor -%}
{%- if not has_webdav and server_check_path %}
option httpchk GET {{ server_check_path }}
{% endif -%}
{% endfor %}
{% set part_list = [] -%}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl', {}) %}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{#
XXX: This template only supports exactly one IPv4 and (if ipv6 is used) one IPv6
per partition. No more (undefined result), no less (IndexError).
-#}
# TODO: insert varnish between apache & haproxy.
# And think of a way to specify which urls goe through varnish, which go
# directly to haproxy. (maybe just passing literal configuration file chunk)
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set apache_ip_list = [ipv4] -%}
{% if ipv6_set -%}
{% set ipv6 = (ipv6_set | list)[0] -%}
{% do apache_ip_list.append('[' ~ ipv6 ~ ']') -%}
{% endif -%}
[simplefile]
recipe = slapos.recipe.template:jinja2
template = inline:{{ '{{ content }}' }}
{% macro simplefile(section_name, file_path, content, mode='') -%}
{% set content_section_name = section_name ~ '-content' -%}
[{{ content_section_name }}]
content = {{ dumps(content) }}
[{{ section(section_name) }}]
< = simplefile
rendered = {{ file_path }}
context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}
{% if use_ipv6 -%}
[zope-tunnel-base]
recipe = slapos.cookbook:ipv4toipv6
runner-path = ${directory:services}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = {{ ipv4 }}
{% endif -%}
{% set haproxy_dict = {} -%}
{% set apache_dict = {} -%}
{% set next_port = slapparameter_dict['tcpv4-port'] -%}
{% for family_name, parameter_id_list in slapparameter_dict['zope-family-dict'].items() -%}
{% set zope_family_address_list = [] -%}
{% set has_webdav = [] -%}
{% for parameter_id in parameter_id_list -%}
{% set zope_address_list = slapparameter_dict[parameter_id] -%}
{% for zope_address, maxconn, webdav in zope_address_list -%}
{% if webdav -%}
{% do has_webdav.append(None) %}
{% endif -%}
{% if use_ipv6 -%}
[{{ section('zope-tunnel-' ~ next_port) }}]
< = zope-tunnel-base
base-name = {{ 'zeo-tunnel-' ~ next_port }}
ipv4-port = {{ next_port }}
ipv6-port = {{ zope_address.split(']:')[1] }}
ipv6 = {{ zope_address.split(']:')[0][1:] }}
{% set zope_effective_address = ipv4 ~ ":" ~ next_port -%}
{% set next_port = next_port + 1 -%}
{% else -%}
{% set zope_effective_address = zope_address -%}
{% endif -%}
{% do zope_family_address_list.append((zope_effective_address, maxconn, webdav)) -%}
{% endfor -%}
{% endfor -%}
{# Make rendering fail artificially if any family has no known backend.
# This is useful as haproxy's hot-reconfiguration mechanism is
# supervisord-incompatible.
# As jinja2 postpones KeyError until place-holder value is actually used,
# do a no-op getitem.
-#}
{% do zope_family_address_list[0][0] -%}
{% set haproxy_port = next_port -%}
{% set next_port = next_port + 1 -%}
{% do haproxy_dict.__setitem__(family_name, (haproxy_port, zope_family_address_list)) -%}
{% if has_webdav -%}
{% set internal_scheme = 'http' -%}{# mod_rewrite does not recognise webdav scheme -#}
{% set external_scheme = 'webdavs' -%}
{% else %}
{% set internal_scheme = 'http' -%}
{% set external_scheme = 'https' -%}
{% endif -%}
{% do apache_dict.__setitem__(family_name, (next_port, external_scheme, internal_scheme ~ '://' ~ ipv4 ~ ':' ~ haproxy_port ~ slapparameter_dict['backend-path'])) -%}
{% set next_port = next_port + 1 -%}
{% endfor -%}
[haproxy-cfg-parameter-dict]
socket-path = ${directory:run}/haproxy.sock
server-check-path = {{ dumps(slapparameter_dict['haproxy-server-check-path']) }}
backend-dict = {{ dumps(haproxy_dict) }}
ip = {{ ipv4 }}
[haproxy-cfg]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-haproxy-cfg'] }}
rendered = ${directory:etc}/haproxy.cfg
context = section parameter_dict haproxy-cfg-parameter-dict
extensions = jinja2.ext.do
[{{ section('haproxy') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/haproxy
command-line = "{{ parameter_dict['haproxy'] }}/sbin/haproxy" -f "${haproxy-cfg:rendered}"
{# TODO: build socat and wrap it as "${directory:bin}/haproxy-ctl" to connect to "${haproxy-cfg-parameter-dict:socket-path}" #}
[apache-conf-ssl]
cert = ${directory:apache-conf}/apache.crt
key = ${directory:apache-conf}/apache.pem
ca-cert = ${directory:apache-conf}/ca.crt
crl = ${directory:apache-conf}/crl.pem
[apache-conf-parameter-dict]
backend-list = {{ dumps(apache_dict.values()) }}
ip-list = {{ dumps(apache_ip_list) }}
pid-file = ${directory:run}/apache.pid
error-log = ${directory:log}/apache-error.log
access-log = ${directory:log}/apache-access.log
# Apache 2.4's default value (60 seconds) can be a bit too short
timeout = 300
# Basic SSL server configuration
cert = ${apache-ssl:cert}
key = ${apache-ssl:key}
cipher =
ssl-session-cache = ${directory:log}/apache-ssl-session-cache
# Client x509 auth
ca-cert = ${apache-ssl-client:cert}
crl = ${apache-ssl-client:crl}
[apache-conf]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-apache-conf'] }}
rendered = ${directory:apache-conf}/apache.conf
context = section parameter_dict apache-conf-parameter-dict
[{{ section('apache') }}]
recipe = slapos.cookbook:wrapper
wrapper-path = ${directory:services}/apache
command-line = "{{ parameter_dict['apache'] }}/bin/httpd" -f "${apache-conf:rendered}" -DFOREGROUND
[{{ section('apache-promise') }}]
# Check any apache port in ipv4, expect other ports and ipv6 to behave consistently
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/apache
hostname = {{ ipv4 }}
port = {{ apache_dict.values()[0][0] }}
[publish]
recipe = slapos.cookbook:publish.serialised
{% for family_name, (apache_port, scheme, _) in apache_dict.items() -%}
{{ family_name ~ '-v6' }} = {% if ipv6_set %}{{ scheme ~ '://[' ~ ipv6 ~ ']:' ~ apache_port }}{% endif %}
{{ family_name }} = {{ scheme ~ '://' ~ ipv4 ~ ':' ~ apache_port }}
{% endfor -%}
[apache-ssl]
{% if ssl_parameter_dict.get('key') -%}
key = ${apache-ssl-key:rendered}
cert = ${apache-ssl-cert:rendered}
{{ simplefile('apache-ssl-key', '${apache-conf-ssl:key}', ssl_parameter_dict['key']) }}
{{ simplefile('apache-ssl-cert', '${apache-conf-ssl:cert}', ssl_parameter_dict['cert']) }}
{% else %}
recipe = plone.recipe.command
command = "{{ parameter_dict['openssl'] }}/bin/openssl" req -newkey rsa -batch -new -x509 -days 3650 -nodes -keyout "${:key}" -out "${:cert}"
key = ${apache-conf-ssl:key}
cert = ${apache-conf-ssl:cert}
{%- endif %}
[apache-ssl-client]
{% if ssl_parameter_dict.get('ca-cert') -%}
cert = ${apache-ssl-ca:rendered}
crl = ${apache-ssl-crl:rendered}
{{ simplefile('apache-ssl-ca', '${apache-conf-ssl:ca-cert}', ssl_parameter_dict['ca-cert']) }}
{{ simplefile('apache-ssl-crl', '${apache-conf-ssl:crl}', ssl_parameter_dict['crl']) }}
{% else %}
cert =
crl =
{%- endif %}
[logrotate-apache]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = apache
log = ${apache-conf-parameter-dict:error-log} ${apache-conf-parameter-dict:access-log}
post = {{ parameter_dict['bin-directory'] }}/slapos-kill --pidfile ${apache-conf-parameter-dict:pid-file} -s USR1
[directory]
recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
promise = ${directory:etc}/promise
services = ${:etc}/run
var = ${buildout:directory}/var
run = ${:var}/run
log = ${:var}/log
ca-dir = ${buildout:directory}/srv/ssl
requests = ${:ca-dir}/requests
private = ${:ca-dir}/private
certs = ${:ca-dir}/certs
newcerts = ${:ca-dir}/newcerts
crl = ${:ca-dir}/crl
[buildout]
extends = {{ logrotate_cfg }}
parts +=
publish
logrotate-apache
{{ part_list | join('\n ') }}
{% if software_type == slap_software_type -%}
{% set json = json_module.loads(parameter_dict.get('cloudooo-json', '{}')) -%}
{% set bin_directory = parameter_dict['buildout-bin-directory'] -%} {% set bin_directory = parameter_dict['buildout-bin-directory'] -%}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
[buildout] [buildout]
parts = parts =
publish-cloudooo-connection-information publish-cloudooo-connection-information
...@@ -8,21 +7,24 @@ parts = ...@@ -8,21 +7,24 @@ parts =
resiliency-exclude-file resiliency-exclude-file
promise promise
promise-openoffice promise-openoffice
eggs-directory = {{ eggs_directory }} {% if use_ipv6 %}promise-tunnel{% endif %}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[publish-cloudooo-connection-information] [publish-cloudooo-connection-information]
recipe = slapos.cookbook:publishurl recipe = slapos.cookbook:publish.serialised
{% if use_ipv6 -%}
url = cloudooo://[${ipv6toipv4:ipv6}]:${ipv6toipv4:ipv6-port}/
{% else -%}
url = cloudooo://${cloudooo-instance:ip}:${cloudooo-instance:port}/ url = cloudooo://${cloudooo-instance:ip}:${cloudooo-instance:port}/
{% endif -%}
[cloudooo-instance] [cloudooo-instance]
recipe = slapos.cookbook:generic.cloudooo recipe = slapos.cookbook:generic.cloudooo
# Network options # Network options
ip = ${slap-network-information:local-ipv4} ip = {{ (ipv4_set | list)[0] }}
port = 23000 {% set tcpv4_port = slapparameter_dict['tcpv4-port'] -%}
openoffice-port = 23060 port = {{ tcpv4_port }}
openoffice-port = {{ tcpv4_port + 1 }}
# Paths # Paths
configuration-file = ${directory:etc}/cloudooo.cfg configuration-file = ${directory:etc}/cloudooo.cfg
...@@ -46,7 +48,8 @@ recipe = slapos.cookbook:fontconfig ...@@ -46,7 +48,8 @@ recipe = slapos.cookbook:fontconfig
conf-path = ${directory:etc}/font.conf conf-path = ${directory:etc}/font.conf
font-system-folder = {{ parameter_dict['fonts'] }} font-system-folder = {{ parameter_dict['fonts'] }}
font-folder = ${directory:font} font-folder = ${directory:font}
url-list = {{ json.get('font_url_list', []) | join(' ') }} {# XXX: violates "instanciation happens offline" rule -#}
url-list = {{ dumps(slapparameter_dict.get('font-url-list', []) | join(' ')) }}
service-folder = ${directory:service} service-folder = ${directory:service}
onetimedownload_path = {{ bin_directory }}/onetimedownload onetimedownload_path = {{ bin_directory }}/onetimedownload
...@@ -68,6 +71,25 @@ path = ${directory:promise}/openoffice ...@@ -68,6 +71,25 @@ path = ${directory:promise}/openoffice
hostname = ${cloudooo-instance:ip} hostname = ${cloudooo-instance:ip}
port = ${cloudooo-instance:openoffice-port} port = ${cloudooo-instance:openoffice-port}
{% if use_ipv6 -%}
[promise-tunnel]
recipe = slapos.cookbook:check_port_listening
path = ${directory:promise}/tunnel
hostname = ${ipv6toipv4:ipv6}
port = ${ipv6toipv4:ipv6-port}
[ipv6toipv4]
recipe = slapos.cookbook:ipv6toipv4
runner-path = ${directory:service}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = ${cloudooo-instance:ip}
ipv6 = {{ (ipv6_set | list)[0] }}
ipv6-port = ${cloudooo-instance:port}
ipv4-port = ${cloudooo-instance:port}
base-name = cloudooo-tunnel
{% endif -%}
# rest of parts are candidates for some generic stuff # rest of parts are candidates for some generic stuff
[directory] [directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
...@@ -77,4 +99,3 @@ service = ${:etc}/run ...@@ -77,4 +99,3 @@ service = ${:etc}/run
promise = ${:etc}/promise promise = ${:etc}/promise
cloudooo-data = ${:srv}/cloudooo cloudooo-data = ${:srv}/cloudooo
font = ${:srv}/font font = ${:srv}/font
{% endif %}
[directory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
services = ${:etc}/run
promise = ${:etc}/promise
[erp5-bootstrap]
recipe = slapos.cookbook:erp5.bootstrap
runner-path = ${directory:services}/erp5-bootstrap
{# Note: a random domain name will be picked if several point to the same IP -#}
{% set reverse_hosts = {} -%}
{% for x, y in publish['hosts-dict'].iteritems() -%}
{% do reverse_hosts.__setitem__(y, x) -%}
{% endfor -%}
{# XXX: Expect the first database to be the one to use for catalog. -#}
{% set mysql_parsed = urlparse.urlparse(publish['mariadb-database-list'][0]) -%}
mysql-url = {{ dumps(urlparse.urlunparse(mysql_parsed[:1] + (mysql_parsed.username + ":" + mysql_parsed.password + "@" + reverse_hosts.get(mysql_parsed.hostname, mysql_parsed.hostname) + ':' ~ mysql_parsed.port, ) + mysql_parsed[2:])) }}
{# Pick the first http[s] family found, they should be all equivalent anyway. -#}
{% set family_list = [] -%}
{% for key, value in publish.items() -%}
{% if key.startswith('family-') and value.startswith('http') -%}
{% do family_list.append(value.split('://', 1)) -%}
{% endif -%}
{% endfor -%}
zope-url = {{ dumps(family_list[0][0] + '://' + publish['inituser-login'] + ':' + publish['inituser-password'] + '@' + family_list[0][1] + '/' + publish['site-id']) }}
[promise-erp5-site]
recipe = slapos.cookbook:check_url_available
url = ${erp5-bootstrap:zope-url}
path = ${directory:promise}/erp5-site
dash_path = {{ parameter_dict['dash-location'] }}/bin/dash
curl_path = {{ parameter_dict['curl-location'] }}/bin/curl
[buildout]
parts = promise-erp5-site
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
{# To create the script (wrapper) which creates the ERP5Site object, pieces
# of what is published by extended file are required. Because they are not
# available at the time the file you are reading is rendered, and because
# those values are composed (lists, dicts...) of which items are needed,
# they cannot be accessed. Instead, make buildout provide these values to
# a second template, rendered at a convenient time.
-#}
[instance-create-erp5-site-real-parameters]
dash-location = {{ parameter_dict['dash-location'] }}
curl-location = {{ parameter_dict['curl-location'] }}
[instance-create-erp5-site-real]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['template-create-erp5-site-real'] }}
rendered = ${buildout:directory}/instance-create-erp5-site-real.cfg
extensions = jinja2.ext.do
context =
import urlparse urlparse
section publish publish
section parameter_dict instance-create-erp5-site-real-parameters
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
[instance-create-erp5-site-real-run]
recipe = slapos.recipe.build
script =
import subprocess, sys
subprocess.check_call([
sys.argv[0],
"buildout:directory=${buildout:directory}",
"buildout:installed=.installed-${:_buildout_section_name_}.cfg",
"-Uoc", self.options['run'],
])
run = ${instance-create-erp5-site-real:rendered}
slapos_promise =
[buildout]
extends = {{ parameter_dict['instance-erp5'] }}
parts +=
instance-create-erp5-site-real-run
{% if slap_software_type == software_type -%}
#############################
#
# Request erp5 production environnment
#
#############################
[buildout]
parts =
request-tidstorage
basedirectory
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
versions = versions
[request-common]
recipe = slapos.cookbook:request
software-url = ${slap-connection:software-release-url}
return = url
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
[request-mariadb]
<=request-common
name = MariaDB DataBase
software-type = mariadb
config-mariadb-json = ${slap-parameter:mariadb-json}
sla-computer_guid = ${slap-parameter:mariadb-computer-guid}
[request-cloudooo]
<=request-common
name = Cloudooo
config-cloudooo-json = ${slap-parameter:cloudooo-json}
software-type = cloudooo
sla-computer_guid = ${slap-parameter:cloudooo-computer-guid}
[request-memcached]
<=request-common
name = Memcached
software-type = memcached
sla-computer_guid = ${slap-parameter:memcached-computer-guid}
[request-kumofs]
<=request-common
name = KumoFS
software-type = kumofs
sla-computer_guid = ${slap-parameter:kumofs-computer-guid}
[request-tidstorage]
<=request-common
name = TidStorage
return = url-login
config-json = ${slap-parameter:json}
config-mysql-url = ${request-mariadb:connection-url}
config-memcached-url = ${request-memcached:connection-url}
config-cloudooo-url = ${request-cloudooo:connection-url}
config-kumofs-url = ${request-kumofs:connection-url}
config-bt5 = ${slap-parameter:bt5}
config-bt5-repository-url = ${slap-parameter:bt5-repository-url}
config-smtp-url = ${slap-parameter:smtp-url}
software-type = tidstorage
sla-computer_guid = ${slap-parameter:tidstorage-computer-guid}
[request-varnish]
<=request-common
name = Varnish
config-tidstorage-url = ${request-tidstorage:connection-url-login}
config-web-checker-mail-address = ${slap-parameter:web-checker-mail-address}
config-web-checker-smtp-host = ${slap-parameter:web-checker-smtp-host}
software-type = varnish
sla-computer_guid = ${slap-parameter:varnish-computer-guid}
[slap-parameter]
# Default value if no computer_guid is specified for each type
mariadb-computer-guid = ${slap-connection:computer-id}
cloudooo-computer-guid = ${slap-connection:computer-id}
memcached-computer-guid = ${slap-connection:computer-id}
kumofs-computer-guid = ${slap-connection:computer-id}
tidstorage-computer-guid = ${slap-connection:computer-id}
varnish-computer-guid = ${slap-connection:computer-id}
cloudooo-json =
bt5 = {{ bt5_list }}
bt5-repository-url = {{ local_bt5_repository }}
smtp-url = smtp://localhost:25/
[basedirectory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc/run
{% endif %}
[versions]
slapos.core = {{ slapos_core_version }}
#############################
#
# Request erp5 development environnment
#
#############################
[buildout]
extends = {{ template_zope }}
parts +=
request-mariadb
request-cloudooo
request-memcached
request-kumofs
basedirectory
test-runner
erp5-bootstrap
erp5-promise
promise-erp5-site
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
versions = versions
[slap-parameter]
# default site id
site-id = erp5
cloudooo-json =
promise-path = ${rootdirectory:etc}/erp5promise.cfg
bt5 = {{ bt5_list }}
bt5-repository-url = {{ local_bt5_repository }}
smtp-url = smtp://localhost:25/
[test-runner]
recipe = slapos.cookbook:erp5.test
certificate-authority-path = ${test-certificate-authority:ca-dir}
mysql-url = ${request-mariadb:connection-url}
kumofs-url = ${request-kumofs:connection-url}
memcached-url = ${request-memcached:connection-url}
cloudooo-url = ${request-cloudooo:connection-url}
test-instance-path = ${directory:unit-test-path}
prepend-path = ${buildout:bin-directory}
run-unit-test = ${buildout:bin-directory}/runUnitTest
run-test-suite = ${buildout:bin-directory}/runTestSuite
openssl-binary = ${test-certificate-authority:openssl-binary}
run-unit-test-binary = {{ bin_directory }}/runUnitTest
run-test-suite-binary = {{ bin_directory }}/runTestSuite
[test-certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ openssl_location }}/bin/openssl
ca-dir = ${directory:test-ca-dir}
requests-directory = ${test-cadirectory:requests}
wrapper = ${basedirectory:services}/test-ca
ca-private = ${test-cadirectory:private}
ca-certs = ${test-cadirectory:certs}
ca-newcerts = ${test-cadirectory:newcerts}
ca-crl = ${test-cadirectory:crl}
[test-cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = ${directory:test-ca-dir}/requests
private = ${directory:test-ca-dir}/private
certs = ${directory:test-ca-dir}/certs
newcerts = ${directory:test-ca-dir}/newcerts
crl = ${directory:test-ca-dir}/crl
[erp5-bootstrap]
recipe = slapos.cookbook:erp5.bootstrap
runner-path = ${basedirectory:services}/erp5-bootstrap
mysql-url = ${request-mariadb:connection-url}
zope-url = http://${zope-instance:user}:${zope-instance:password}@${zope-instance:ip}:${zope-instance:port}/${slap-parameter:site-id}
[erp5-promise]
recipe = slapos.cookbook:erp5.promise
promise-path = ${slap-parameter:promise-path}
kumofs-url = ${request-kumofs:connection-url}
memcached-url = ${request-memcached:connection-url}
cloudooo-url = ${request-cloudooo:connection-url}
smtp-url = ${slap-parameter:smtp-url}
bt5 = ${slap-parameter:bt5}
bt5-repository-url = ${slap-parameter:bt5-repository-url}
[request-common]
recipe = slapos.cookbook:request
software-url = ${slap-connection:software-release-url}
sla-computer_guid = ${slap-connection:computer-id}
return = url
server-url = ${slap-connection:server-url}
key-file = ${slap-connection:key-file}
cert-file = ${slap-connection:cert-file}
computer-id = ${slap-connection:computer-id}
partition-id = ${slap-connection:partition-id}
[request-mariadb]
<=request-common
name = MariaDB DataBase
software-type = mariadb
[request-cloudooo]
<=request-common
name = Cloudooo
config-cloudooo-json = ${slap-parameter:cloudooo-json}
software-type = cloudooo
[request-memcached]
<=request-common
name = Memcached
software-type = memcached
[request-kumofs]
<=request-common
name = KumoFS
software-type = kumofs
[zope-instance]
promise-path = ${slap-parameter:promise-path}
site-id = ${slap-parameter:site-id}
[directory]
test-ca-dir = ${rootdirectory:srv}/test-ca
test-instance-path = ${rootdirectory:srv}/test-instance
unit-test-path = ${:test-instance-path}/unit_test
[promise-erp5-site]
recipe = slapos.cookbook:check_url_available
path = ${basedirectory:promises}/erp5site
url = http://${zope-instance:ip}:${zope-instance:port}/${slap-parameter:site-id}
dash_path = {{ dash_location }}/bin/dash
curl_path = {{ curl_location }}/bin/curl
[versions]
slapos.core = {{ slapos_core_version }}
{% import "root_common" as root_common with context %}
{% set frontend_dict = slapparameter_dict.get('frontend', {}) -%}
{% set has_frontend = frontend_dict.get('software-url', '') != '' -%}
{% set site_id = slapparameter_dict.get('site-id', 'erp5') -%}
{% set inituser_login = slapparameter_dict.get('inituser-login', 'zope') -%}
{% set publish_dict = {'site-id': site_id, 'inituser-login': inituser_login} -%}
[request-common]
<= request-common-base
config-use-ipv6 = {{ dumps(slapparameter_dict.get('use-ipv6', False)) }}
{% macro request(name, software_type, config_key, config, ret={'url': True}) -%}
{% do config.update(slapparameter_dict.get(config_key, {})) -%}
{% set section = 'request-' ~ name -%}
[{{ section }}]
<= request-common
name = {{ name }}
software-type = {{ software_type }}
return = {{ ' '.join(ret) }}
{% for ret, publish in ret.iteritems() -%}
{% if publish -%}
{% do publish_dict.__setitem__(name ~ '-' ~ ret, '${' ~ section ~ ':connection-' ~ ret ~ '}')%}
{% endif -%}
{% endfor -%}
{{ root_common.sla(name) }}
{% for k, v in config.iteritems() -%}
config-{{ k }} = {{ dumps(v) }}
{% endfor -%}
{% endmacro -%}
{{ request('memcached-persistent', 'kumofs', 'kumofs', {'tcpv4-port': 2000}) }}
{{ request('memcached-volatile', 'kumofs', 'memcached', {'tcpv4-port': 2010, 'ram-storage-size': 64}) }}
{{ request('cloudooo', 'cloudooo', 'cloudooo', {'tcpv4-port': 2020}) }}
{{ request('mariadb', 'mariadb', 'mariadb', {'tcpv4-port': 2099}, {'database-list': True, 'test-database-list': True}) }}
{# ZODB -#}
{% set zodb_dict = {} -%}
{% set storage_dict = {} -%}
{% set mountpoints = set() -%}
{% for zodb in slapparameter_dict.get('zodb') or ({'type': 'zeo', 'server': {}},) -%}
{% do mountpoints.add(zodb.setdefault('mount-point', '/')) -%}
{% set name = zodb.pop('name', 'root') -%}
{% do assert(name not in zodb_dict, name, zodb_dict) -%}
{% do zodb_dict.__setitem__(name, zodb) -%}
{% if 'server' in zodb -%}
{% do storage_dict.setdefault(zodb['type'], {}).__setitem__(name, zodb.pop('server')) -%}
{% endif -%}
{% endfor -%}
{% do assert(len(mountpoints) == len(zodb_dict)) -%}
{% set neo = [] -%}
{% for server_type, server_dict in storage_dict.iteritems() -%}
{% if server_type == 'neo' -%}
{% set ((name, server_dict),) = server_dict.items() -%}
{% do neo.append(server_dict.get('cluster')) -%}
{% do server_dict.__setitem__('cluster', '${publish-early:neo-cluster}') -%}
{{ root_common.request_neo(server_dict, 'zodb-neo', 'neo-') }}
{% else -%}
{{ assert(server_type == 'zeo', server_type) -}}
{# BBB: for compatibility, keep 'zodb' as partition_reference for ZEO -#}
{{ request('zodb', 'zodb-' ~ server_type, 'zodb-' ~ server_type, {'tcpv4-port': 2100, 'zodb-dict': server_dict}, dict.fromkeys(('storage-dict', 'tidstorage-ip', 'tidstorage-port'))) }}
{% endif -%}
{% endfor -%}
[publish-early]
recipe = slapos.cookbook:publish-early
-init =
inituser-password gen-password:passwd
deadlock-debugger-password gen-deadlock-debugger-password:passwd
{%- if neo %}
neo-cluster gen-neo-cluster:name
{%- if neo[0] %}
neo-cluster = {{ neo[0] }}
{%- endif %}
{%- endif %}
{%- set inituser_password = slapparameter_dict.get('inituser-password') %}
{%- if inituser_password %}
inituser-password = {{ inituser_password }}
{%- endif %}
{%- set deadlock_debugger_password = slapparameter_dict.get('deadlock-debugger-password') -%}
{%- if deadlock_debugger_password %}
deadlock-debugger-password = {{ deadlock_debugger_password }}
{%- endif %}
[gen-password]
recipe = slapos.cookbook:generate.password
storage-path =
[gen-deadlock-debugger-password]
<= gen-password
[gen-neo-cluster-base]
<= gen-password
[gen-neo-cluster]
name = neo-${gen-neo-cluster-base:passwd}
[request-zope-base]
<= request-common
return =
zope-address-list
hosts-dict
config-bt5 = {{ dumps(slapparameter_dict.get('bt5', 'erp5_full_text_myisam_catalog erp5_configurator_standard erp5_configurator_maxma_demo erp5_configurator_ung erp5_configurator_run_my_doc')) }}
config-bt5-repository-url = {{ dumps(slapparameter_dict.get('bt5-repository-url', local_bt5_repository)) }}
config-cloudooo-url = ${request-cloudooo:connection-url}
config-deadlock-debugger-password = ${publish-early:deadlock-debugger-password}
config-developer-list = {{ dumps(slapparameter_dict.get('developer-list', [inituser_login])) }}
config-hosts-dict = {{ dumps(slapparameter_dict.get('hosts-dict', {})) }}
config-hostalias-dict = {{ dumps(slapparameter_dict.get('hostalias-dict', {})) }}
config-inituser-login = {{ dumps(inituser_login) }}
config-inituser-password = ${publish-early:inituser-password}
config-kumofs-url = ${request-memcached-persistent:connection-url}
config-memcached-url = ${request-memcached-volatile:connection-url}
config-mysql-test-url-list = ${request-mariadb:connection-test-database-list}
config-mysql-url-list = ${request-mariadb:connection-database-list}
config-site-id = {{ dumps(site_id) }}
config-smtp-url = {{ dumps(slapparameter_dict.get('smtp-url', 'smtp://localhost:25/')) }}
config-timezone = {{ dumps(slapparameter_dict.get('timezone', 'UTC')) }}
config-zodb-dict = {{ dumps(zodb_dict) }}
{% for server_type, server_dict in storage_dict.iteritems() -%}
{% if server_type == 'neo' -%}
config-neo-cluster = ${publish-early:neo-cluster}
config-neo-name = {{ server_dict.keys()[0] }}
config-neo-masters = ${neo-0-final:connection-masters}
{% else -%}
config-zodb-zeo = ${request-zodb:connection-storage-dict}
config-tidstorage-ip = ${request-zodb:connection-tidstorage-ip}
config-tidstorage-port = ${request-zodb:connection-tidstorage-port}
{% endif -%}
{% endfor -%}
software-type = zope
{% set zope_family_dict = {} -%}
{% for custom_name, zope_parameter_dict in slapparameter_dict.get('zope-partition-dict', {'1': {}}).items() -%}
{% set partition_name = 'zope-' ~ custom_name -%}
{% set section_name = 'request-' ~ partition_name -%}
{% do zope_family_dict.setdefault(zope_parameter_dict.get('family', 'default'), []).append(section_name) -%}
[{{ section_name }}]
<= request-zope-base
name = {{ partition_name }}
{{ root_common.sla(partition_name) }}
config-name = {{ dumps(custom_name) }}
config-instance-count = {{ dumps(zope_parameter_dict.get('instance-count', 1)) }}
config-thread-amount = {{ dumps(zope_parameter_dict.get('thread-amount', 4)) }}
config-timerserver-interval = {{ dumps(zope_parameter_dict.get('timerserver-interval', 5)) }}
config-longrequest-logger-interval = {{ dumps(zope_parameter_dict.get('longrequest-logger-interval', -1)) }}
config-longrequest-logger-timeout = {{ dumps(zope_parameter_dict.get('longrequest-logger-timeout', 1)) }}
config-port-base = {{ dumps(zope_parameter_dict.get('port-base', 2200)) }}
config-webdav = {{ dumps(zope_parameter_dict.get('webdav', False)) }}
{% endfor -%}
{# We need to concatenate lists that we cannot read as lists, so this gets hairy. -#}
{% set zope_address_list_id_dict = {} -%}
{% set zope_family_parameter_dict = {} -%}
{% for family_name, zope_section_id_list in zope_family_dict.items() -%}
{% for zope_section_id in zope_section_id_list -%}
{% set parameter_name = 'zope-family-entry-' ~ zope_section_id -%}
{% do zope_address_list_id_dict.__setitem__(zope_section_id, parameter_name) -%}
{% do zope_family_parameter_dict.setdefault(family_name, []).append(parameter_name) -%}
{% endfor -%}
{% if has_frontend -%}
{% set frontend_name = 'frontend-' ~ family_name -%}
{% do publish_dict.__setitem__('family-' ~ family_name, '${' ~ frontend_name ~ ':connection-site_url}' ) -%}
[{{ frontend_name }}]
<= request-frontend-base
name = {{ frontend_name }}
config-url = ${request-balancer:{{ family_name }}-v6}
{% else -%}
{% do publish_dict.__setitem__('family-' ~ family_name, '${request-balancer:connection-' ~ family_name ~ '}' ) -%}
{% do publish_dict.__setitem__('family-' ~ family_name ~ '-v6', '${request-balancer:connection-' ~ family_name ~ '-v6}' ) -%}
{% endif -%}
{% endfor -%}
{% set balancer_dict = slapparameter_dict.get('balancer', {}) -%}
[request-balancer]
<= request-common
name = balancer
software-type = balancer
{{ root_common.sla('balancer') }}
return =
{%- for family in zope_family_dict %}
{{ family }}
{{ family }}-v6
{% endfor -%}
config-zope-family-dict = {{ dumps(zope_family_parameter_dict) }}
config-tcpv4-port = {{ dumps(balancer_dict.get('tcpv4-port', 2150)) }}
{% for zope_section_id, name in zope_address_list_id_dict.items() -%}
config-{{ name }} = {{ ' ${' ~ zope_section_id ~ ':connection-zope-address-list}' }}
{% endfor -%}
# XXX: should those really be same for all families ?
config-haproxy-server-check-path = {{ dumps(balancer_dict.get('haproxy-server-check-path', '/') % {'site-id': site_id}) }}
config-backend-path = {{ dumps(balancer_dict.get('apache-backend-path', '/') % {'site-id': site_id}) }}
config-ssl = {{ dumps(balancer_dict.get('ssl', {})) }}
[request-frontend-base]
{% if has_frontend -%}
<= request-common
software-url = {{ dumps(frontend_dict['software-url']) }}
software-type = {{ dumps(frontend_dict.get('software-type', 'RootSoftwareInstance')) }}
{{ root_common.sla('frontend', True) }}
slave = true
{% set config_dict = {
'type': 'zope',
} -%}
{% if frontend_dict.get('domain') -%}
{% do config_dict.__setitem__('custom_domain', frontend_dict['domain']) -%}
{% endif -%}
{% for name, value in config_dict.items() -%}
config-{{ name }} = {{ value }}
{% endfor -%}
return = site_url
{% endif -%}
[publish]
recipe = slapos.cookbook:publish.serialised
-extends = publish-early
{% if 'neo' in storage_dict -%}
neo-masters = ${neo-0-final:connection-masters}
neo-admins = ${neo-0-final:connection-admins}
{% endif -%}
{#
Pick any published hosts-dict, they are expected to be identical - and there is
no way to check here.
-#}
hosts-dict = {{ '${' ~ zope_address_list_id_dict.keys()[0] ~ ':connection-hosts-dict}' }}
{% for name, value in publish_dict.items() -%}
{{ name }} = {{ value }}
{% endfor -%}
{{ root_common.common_section() }}
{% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
[buildout] [buildout]
parts = extends = {{ logrotate_cfg }}
parts +=
publish-kumofs-connection-information publish-kumofs-connection-information
kumofs-instance kumofs-instance
logrotate
logrotate-entry-kumofs logrotate-entry-kumofs
cron
cron-entry-logrotate
resiliency-exclude-file resiliency-exclude-file
promise-kumofs-server promise-kumofs-server
promise-kumofs-server-listen promise-kumofs-server-listen
promise-kumofs-gateway promise-kumofs-gateway
promise-kumofs-manager promise-kumofs-manager
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[publish-kumofs-connection-information] [publish-kumofs-connection-information]
recipe = slapos.cookbook:publishurl recipe = slapos.cookbook:publish.serialised
{% if use_ipv6 -%}
url = memcached://[${kumofs-instance:ip}]:${kumofs-instance:gateway-port}/
{% else -%}
url = memcached://${kumofs-instance:ip}:${kumofs-instance:gateway-port}/ url = memcached://${kumofs-instance:ip}:${kumofs-instance:gateway-port}/
{% endif -%}
[kumofs-instance] [kumofs-instance]
recipe = slapos.cookbook:generic.kumofs recipe = slapos.cookbook:generic.kumofs
# Network options # Network options
ip = ${slap-network-information:local-ipv4} {% if use_ipv6 -%}
manager-port = 13101 ip = {{ (ipv6_set | list)[0] }}
server-port = 13201 address-family = inet6
server-listen-port = 13202 {% else -%}
gateway-port = 13301 ip = {{ (ipv4_set | list)[0] }}
address-family = inet4
{% endif -%}
{% set tcpv4_port = slapparameter_dict['tcpv4-port'] -%}
manager-port = {{ tcpv4_port }}
server-port = {{ tcpv4_port + 1 }}
server-listen-port = {{ tcpv4_port + 2 }}
gateway-port = {{ tcpv4_port + 3 }}
# Paths: Data
{% set ram_storage_size = slapparameter_dict.get('ram-storage-size') -%}
{% if ram_storage_size -%}
data-path = *#capsiz={{ ram_storage_size }}m
{% else -%}
# (with 10M buckets and HDBTLARGE option)
data-path = ${directory:kumofs-data}/kumodb.tch#bnum=10485760#opts=l
{% endif -%}
# Paths: Running wrappers # Paths: Running wrappers
gateway-wrapper = ${basedirectory:services}/kumofs_gateway gateway-wrapper = ${directory:services}/kumofs_gateway
manager-wrapper = ${basedirectory:services}/kumofs_manager manager-wrapper = ${directory:services}/kumofs_manager
server-wrapper = ${basedirectory:services}/kumofs_server server-wrapper = ${directory:services}/kumofs_server
# Paths: Data (with 10M buckets and HDBTLARGE option)
data-path = ${directory:kumofs-data}/kumodb.tch#bnum=10485760#opts=l
# Paths: Logs # Paths: Logs
kumo-gateway-log = ${basedirectory:log}/kumo-gateway.log kumo-gateway-log = ${directory:log}/kumo-gateway.log
kumo-manager-log = ${basedirectory:log}/kumo-manager.log kumo-manager-log = ${directory:log}/kumo-manager.log
kumo-server-log = ${basedirectory:log}/kumo-server.log kumo-server-log = ${directory:log}/kumo-server.log
# Binary information # Binary information
kumo-gateway-binary = {{ kumo_location }}/bin/kumo-gateway kumo-gateway-binary = {{ parameter_dict['kumo-location'] }}/bin/kumo-gateway
kumo-manager-binary = {{ kumo_location }}/bin/kumo-manager kumo-manager-binary = {{ parameter_dict['kumo-location'] }}/bin/kumo-manager
kumo-server-binary = {{ kumo_location }}/bin/kumo-server kumo-server-binary = {{ parameter_dict['kumo-location'] }}/bin/kumo-server
shell-path = {{ dash_location }}/bin/dash shell-path = {{ parameter_dict['dash-location'] }}/bin/dash
[logrotate-entry-kumofs] [logrotate-entry-kumofs]
<= logrotate
recipe = slapos.cookbook:logrotate.d recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = kumofs name = kumofs
log = ${kumofs-instance:kumo-gateway-log} ${kumofs-instance:kumo-manager-log} log = ${kumofs-instance:kumo-gateway-log} ${kumofs-instance:kumo-manager-log} ${kumofs-instance:kumo-server-log}
${kumofs-instance:kumo-server-log}
# rest of parts are candidates for some generic stuff
[logrotate]
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = {{ logrotate_location }}/usr/sbin/logrotate
gzip-binary = {{ gzip_location }}/bin/gzip
gunzip-binary = {{ gzip_location }}/bin/gunzip
# Directories
wrapper = ${rootdirectory:bin}/logrotate
conf = ${rootdirectory:etc}/logrotate.conf
logrotate-entries = ${directory:logrotate-entries}
backup = ${directory:logrotate-backup}
state-file = ${rootdirectory:srv}/logrotate.status
[basedirectory]
recipe = slapos.cookbook:mkdirectory
log = ${rootdirectory:var}/log
services = ${rootdirectory:etc}/run
promise = ${rootdirectory:etc}/promise
run = ${rootdirectory:var}/run
backup = ${rootdirectory:srv}/backup
[directory] [directory]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:mkdirectory
cron-entries = ${rootdirectory:etc}/cron.d log = ${buildout:directory}/var/log
crontabs = ${rootdirectory:etc}/crontabs services = ${buildout:directory}/etc/run
cronstamps = ${rootdirectory:etc}/cronstamps promise = ${buildout:directory}/etc/promise
logrotate-backup = ${basedirectory:backup}/logrotate
logrotate-entries = ${rootdirectory:etc}/logrotate.d
kumofs-data = ${rootdirectory:srv}/kumofs
[rootdirectory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
var = ${buildout:directory}/var
srv = ${buildout:directory}/srv srv = ${buildout:directory}/srv
bin = ${buildout:directory}/bin kumofs-data = ${:srv}/kumofs
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ dcron_location }}/sbin/crond
cron-entries = ${directory:cron-entries}
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
binary = ${basedirectory:services}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${rootdirectory:bin}/cron_simplelogger
log = ${basedirectory:log}/cron.log
[cron-entry-logrotate]
<= cron
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
[resiliency-exclude-file] [resiliency-exclude-file]
# Generate rdiff exclude file in case of resiliency # Generate rdiff exclude file in case of resiliency
recipe = collective.recipe.template recipe = collective.recipe.template
input = inline: ** input = inline: **
output = ${rootdirectory:srv}/exporter.exclude output = ${directory:srv}/exporter.exclude
# Deploy zope promises scripts # Deploy zope promises scripts
[promise-template] [promise-template]
...@@ -130,20 +89,20 @@ port = ${kumofs-instance:server-listen-port} ...@@ -130,20 +89,20 @@ port = ${kumofs-instance:server-listen-port}
[promise-kumofs-server] [promise-kumofs-server]
<= promise-template <= promise-template
path = ${basedirectory:promise}/kumofs-server path = ${directory:promise}/kumofs-server
port = ${kumofs-instance:server-port} port = ${kumofs-instance:server-port}
[promise-kumofs-server-listen] [promise-kumofs-server-listen]
<= promise-template <= promise-template
path = ${basedirectory:promise}/kumofs-server-listen path = ${directory:promise}/kumofs-server-listen
port = ${kumofs-instance:server-listen-port} port = ${kumofs-instance:server-listen-port}
[promise-kumofs-gateway] [promise-kumofs-gateway]
<= promise-template <= promise-template
path = ${basedirectory:promise}/kumofs-gateway path = ${directory:promise}/kumofs-gateway
port = ${kumofs-instance:gateway-port} port = ${kumofs-instance:gateway-port}
[promise-kumofs-manager] [promise-kumofs-manager]
<= promise-template <= promise-template
path = ${basedirectory:promise}/kumofs-manager path = ${directory:promise}/kumofs-manager
port = ${kumofs-instance:manager-port} port = ${kumofs-instance:manager-port}
{% if software_type == slap_software_type -%} {% set part_list = [] -%}
{% set json = json_module.loads(slapparameter_dict.get('mariadb-json', '{}')) -%} {% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set backup_periodicity = json.get('backup-periodicity', '0 22 * * *') -%} {% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
{% set bin_directory = parameter_dict['buildout-bin-directory'] -%} {% set database_list = slapparameter_dict.get('database-list', [{'name': 'erp5', 'user': 'user', 'password': 'insecure'}]) -%}
{% set test_database_list = [] %}
[buildout] {% for database_count in range(slapparameter_dict.get('test-database-amount', 1)) -%}
parts = {% do test_database_list.append({'name': 'erp5_test_' ~ database_count, 'user': 'testuser_' ~ database_count, 'password': 'testpassword' ~ database_count}) -%}
publish-mariadb-url {% endfor -%}
mariadb-instance {% set catalog_backup = slapparameter_dict.get('catalog-backup', {}) -%}
logrotate {% set backup_periodicity = slapparameter_dict.get('backup-periodicity', 'daily') -%}
logrotate-entry-mariadb {% set full_backup_retention_days = catalog_backup.get('full-retention-days', 7) -%}
cron {% set incremental_backup_retention_days = catalog_backup.get('incremental-retention-days', full_backup_retention_days) -%}
cron-entry-logrotate {% set port = slapparameter_dict['tcpv4-port'] %}
cron-entry-mariadb-backup {% if use_ipv6 -%}
cron-entry-mariadb-backup-expire {% set ip = (ipv6_set | list)[0] -%}
binary-link {% else -%}
resiliency-exclude-file {% set ip = (ipv4_set | list)[0] -%}
resiliency-after-import-script {% endif -%}
promise
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[publish-mariadb-url] [publish-mariadb-url]
recipe = slapos.cookbook:publishurl recipe = slapos.cookbook:publish.serialised
url = mysql://${mariadb-instance:user}:${mariadb-instance:password}@${mariadb-instance:ip}:${mariadb-instance:port}/${mariadb-instance:database} {% macro render_database_list(database_list) -%}
{% set publish_database_list = [] -%}
[binary-wrap-base] {% for database in database_list -%}
recipe = slapos.cookbook:wrapper {% if database.get('user') -%}
# Note: --defaults-file must be the first argument, otherwise wrapped binary {% do publish_database_list.append("mysql://" ~ database['user'] ~ ":" ~ database['password'] ~ "@" ~ ip ~ ":" ~ port ~ "/" ~ database['name']) -%}
# will reject it. {% else -%}
command-line = "{{ mariadb_location }}/bin/${:command}" --defaults-file="${mariadb-instance:conf-file}" {% do publish_database_list.append("mysql://" ~ ip ~ ":" ~ port ~ "/" ~ database['name']) -%}
wrapper-path = ${rootdirectory:bin}/${:command} {% endif -%}
parameters-extra = true {% endfor -%}
{{ dumps(publish_database_list) }}
[binary-wrap-mysqldump] {% endmacro -%}
< = binary-wrap-base database-list = {{ render_database_list(database_list) }}
command = mysqldump test-database-list = {{ render_database_list(test_database_list) }}
[simplefile]
recipe = slapos.recipe.template:jinja2
template = inline:{{ '{{ content }}' }}
{% macro simplefile(section_name, file_path, content, mode='') -%}
{% set content_section_name = section_name ~ '-content' -%}
[{{ content_section_name }}]
content = {{ dumps(content) }}
[{{ section(section_name) }}]
< = simplefile
rendered = {{ file_path }}
context = key content {{content_section_name}}:content
mode = {{ mode }}
{%- endmacro %}
{% set ssl_dict = {} -%}
{% macro sslfile(key, content, mode='644') -%}
{% set path = '${directory:mariadb-ssl}/' ~ key ~ '.pem' -%}
{% do ssl_dict.__setitem__(key, path) -%}
{{ simplefile('ssl-file-' ~ key, path, content, mode) }}
{%- endmacro %}
{% set ssl_parameter_dict = slapparameter_dict.get('ssl') -%}
{% if ssl_parameter_dict -%}
{% set base_directory = '${directory:mariadb-ssl}/' -%}
{# Note: The key content will be stored in .installed.cfg, and this template's
rendering, so the only point of mode is to avoid risking mariadb complaining
about laxist file mode. -#}
{{ sslfile('key', ssl_parameter_dict['key'], mode='600') }}
{{ sslfile('crt', ssl_parameter_dict['crt']) }}
{% if 'ca-crt' in ssl_parameter_dict -%}
{{ sslfile('ca-crt', ssl_parameter_dict['ca-crt']) }}
{% endif -%}
{% if 'crl' in ssl_parameter_dict -%}
{{ sslfile('crl', ssl_parameter_dict['crl']) }}
{% endif -%}
{%- endif %}
[cron-entry-mariadb-backup] {% if full_backup_retention_days > -1 -%}
[{{ section('cron-entry-mariadb-backup') }}]
recipe = slapos.cookbook:cron.d recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries} cron-entries = ${cron:cron-entries}
name = mariadb-backup name = mariadb-backup
frequency = {{ backup_periodicity }} time = {{ dumps(backup_periodicity) }}
{# When binlogs are enabled: {# When binlogs are enabled:
# flush-logs: used so no manipulation on binlogs is needed to restore from # flush-logs: used so no manipulation on binlogs is needed to restore from
# full + binlogs. The first binlog after a dump starts from dump snapshot and # full + binlogs. The first binlog after a dump starts from dump snapshot and
# can be fully restored. # can be fully restored.
# master-data: use value "2" as we are not in a replication case # master-data: use value "2" as we are not in a replication case
#} #}
command = "${binary-wrap-mysqldump:wrapper-path}" -u root --all-databases --single-transaction --flush-logs --master-data=2 --socket=${mariadb-instance:socket} | {{ gzip_location }}/bin/gzip > "${directory:mariadb-backup-full}/$({{ coreutils_location }}/bin/date "+%Y%m%d%H%M%S").sql.gz" command = "${binary-wrap-mysqldump:wrapper-path}" -u root --all-databases --single-transaction {% if incremental_backup_retention_days > -1 %}--flush-logs --master-data=2 {% endif %}| {{ parameter_dict['gzip-location'] }}/bin/gzip > "${directory:mariadb-backup-full}/$({{ parameter_dict['coreutils-location'] }}/bin/date "+%Y%m%d%H%M%S").sql.gz"
{# KEEP GLOB PATTERN IN SYNC with generated filenames above {# KEEP GLOB PATTERN IN SYNC with generated filenames above
# YYYYmmddHHMMSS -#} # YYYYmmddHHMMSS -#}
file-glob = ??????????????.sql.gz file-glob = ??????????????.sql.gz
[cron-entry-mariadb-backup-expire] {% if full_backup_retention_days > 0 -%}
[{{ section("cron-entry-mariadb-backup-expire") }}]
recipe = slapos.cookbook:cron.d recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries} cron-entries = ${cron:cron-entries}
name = mariadb-backup-expire name = mariadb-backup-expire
frequency = {{ backup_periodicity }} time = {{ dumps(backup_periodicity) }}
command = {{ findutils_location }}/bin/find "${directory:mariadb-backup-full}" -maxdepth 1 -name "${cron-entry-mariadb-backup:file-glob}" -daystart -mtime +7 -delete command = {{ parameter_dict['findutils-location'] }}/bin/find "${directory:mariadb-backup-full}" -maxdepth 1 -name "${cron-entry-mariadb-backup:file-glob}" -daystart -mtime +{{ full_backup_retention_days }} -delete
{%- endif %}
[mariadb-instance] {%- endif %}
# XXX: remove backup part of this recipe. Backup part is now done in previous sections.
# Keeping it is harmless because it is supposed to be launched by cron entry, which has been removed. [my-cnf-parameters]
recipe = slapos.cookbook:generic.mysql ip = {{ ip }}
port = {{ port }}
# Options socket = ${directory:run}/mariadb.sock
user = user data-directory = ${directory:mariadb-data}
parallel-test-database-amount = ${slap-parameter:test-database-amount} pid-file = ${directory:run}/mariadb.pid
port = 45678 error-log = ${directory:log}/mariadb_error.log
ip = ${slap-network-information:local-ipv4} slow-query-log = ${directory:log}/mariadb_slowquery.log
database = erp5 long-query-time = {{ dumps(slapparameter_dict.get('long-query-time', 1)) }}
test-user = erp5_test innodb-buffer-pool-size = {{ dumps(slapparameter_dict.get('innodb-buffer-pool-size', 0)) }}
test-database = erp5_test innodb-log-file-size = {{ dumps(slapparameter_dict.get('innodb-log-file-size', 0)) }}
mysql-test-database-base = testdb innodb-log-buffer-size = {{ dumps(slapparameter_dict.get('innodb-log-buffer-size', 0)) }}
mysql-test-user-base = testuser relaxed-writes = {{ dumps(slapparameter_dict.get('relaxed-writes', False)) }}
{% if incremental_backup_retention_days > -1 -%}
# Backup
binlog-path = ${directory:mariadb-backup-incremental}/binlog binlog-path = ${directory:mariadb-backup-incremental}/binlog
# XXX: binlog rotation happens along with other log's rotation # XXX: binlog rotation happens along with other log's rotation
binlog-expire-days = 7 binlog-expire-days = {{ dumps(incremental_backup_retention_days) }}
{% else %}
# Paths binlog-path =
wrapper = ${basedirectory:services}/mariadb {%- endif %}
update-wrapper = ${basedirectory:services}/mariadb_update {%- for key, value in ssl_dict.items() -%}
backup-script = ${rootdirectory:bin}/innobackupex-controller ssl-{{ key }} = {{ value }}
full-backup-directory = ${directory:mariadb-backup-full} {% endfor %}
incremental-backup-directory = ${directory:mariadb-backup-incremental}
data-directory = ${directory:mariadb-data} [my-cnf]
pid-file = ${basedirectory:run}/mariadb.pid recipe = slapos.recipe.template:jinja2
socket = ${basedirectory:run}/mariadb.sock rendered = ${directory:etc}/mariadb.cnf
error-log = ${basedirectory:log}/mariadb_error.log template = {{ parameter_dict['template-my-cnf'] }}
slow-query-log = ${basedirectory:log}/mariadb_slowquery.log context = section parameter_dict my-cnf-parameters
conf-file = ${rootdirectory:etc}/mariadb.cnf
bin-directory = ${rootdirectory:bin} [init-script-parameters]
innobackupex-incremental = ${rootdirectory:bin}/innobackupex-incremental database-list = {{ dumps(database_list + test_database_list) }}
innobackupex-full = ${rootdirectory:bin}/innobackupex-full
[init-script]
# Binary information recipe = slapos.recipe.template:jinja2
innobackupex-binary = {{ xtrabackup_location }}/bin/innobackupex # XXX: is there a better location ?
mysql-base-directory = {{ mariadb_location }} rendered = ${directory:etc}/mariadb_initial_setup.sql
mysql-binary = {{ mariadb_location }}/bin/mysql template = {{ parameter_dict['template-mariadb-initial-setup'] }}
mysql-install-binary = {{ mariadb_location }}/scripts/mysql_install_db context = section parameter_dict init-script-parameters
mysql-upgrade-binary = {{ mariadb_location }}/bin/mysql_upgrade
mysqld-binary = {{ mariadb_location }}/bin/mysqld [update-mysql]
pt-align-binary = {{ perl_siteprefix }}/bin/pt-align recipe = slapos.cookbook:generic.mysql.wrap_update_mysql
pt-archiver-binary = {{ perl_siteprefix }}/bin/pt-archiver output = ${directory:services}/mariadb_update
pt-config-diff-binary = {{ perl_siteprefix }}/bin/pt-config-diff binary = ${binary-wrap-mysql_upgrade:wrapper-path}
pt-deadlock-logger-binary = {{ perl_siteprefix }}/bin/pt-deadlock-logger mysql = ${binary-wrap-mysql:wrapper-path}
pt-diskstats-binary = {{ perl_siteprefix }}/bin/pt-diskstats init-script = ${init-script:rendered}
pt-duplicate-key-checker-binary = {{ perl_siteprefix }}/bin/pt-duplicate-key-checker mysql_tzinfo_to_sql = ${binary-wrap-mysql_tzinfo_to_sql:wrapper-path}
pt-fifo-split-binary = {{ perl_siteprefix }}/bin/pt-fifo-split
pt-find-binary = {{ perl_siteprefix }}/bin/pt-find [mysqld]
pt-fingerprint-binary = {{ perl_siteprefix }}/bin/pt-fingerprint recipe = slapos.cookbook:generic.mysql.wrap_mysqld
pt-fk-error-logger-binary = {{ perl_siteprefix }}/bin/pt-fk-error-logger output = ${directory:services}/mariadb
pt-heartbeat-binary = {{ perl_siteprefix }}/bin/pt-heartbeat binary = {{ parameter_dict['mariadb-location'] }}/bin/mysqld
pt-index-usage-binary = {{ perl_siteprefix }}/bin/pt-index-usage configuration-file = ${my-cnf:rendered}
pt-ioprofile-binary = {{ perl_siteprefix }}/bin/pt-ioprofile data-directory = ${my-cnf-parameters:data-directory}
pt-kill-binary = {{ perl_siteprefix }}/bin/pt-kill mysql-install-binary = {{ parameter_dict['mariadb-location'] }}/scripts/mysql_install_db
pt-mext-binary = {{ perl_siteprefix }}/bin/pt-mext mysql-base-directory = {{ parameter_dict['mariadb-location'] }}
pt-mysql-summary-binary = {{ perl_siteprefix }}/bin/pt-mysql-summary
pt-online-schema-change-binary = {{ perl_siteprefix }}/bin/pt-online-schema-change
pt-pmp-binary = {{ perl_siteprefix }}/bin/pt-pmp
pt-query-digest-binary = {{ perl_siteprefix }}/bin/pt-query-digest
pt-show-grants-binary = {{ perl_siteprefix }}/bin/pt-show-grants
pt-sift-binary = {{ perl_siteprefix }}/bin/pt-sift
pt-slave-delay-binary = {{ perl_siteprefix }}/bin/pt-slave-delay
pt-slave-find-binary = {{ perl_siteprefix }}/bin/pt-slave-find
pt-slave-restart-binary = {{ perl_siteprefix }}/bin/pt-slave-restart
pt-stalk-binary = {{ perl_siteprefix }}/bin/pt-stalk
pt-summary-binary = {{ perl_siteprefix }}/bin/pt-summary
pt-table-checksum-binary = {{ perl_siteprefix }}/bin/pt-table-checksum
pt-table-sync-binary = {{ perl_siteprefix }}/bin/pt-table-sync
pt-table-usage-binary = {{ perl_siteprefix }}/bin/pt-table-usage
pt-upgrade-binary = {{ perl_siteprefix }}/bin/pt-upgrade
pt-variable-advisor-binary = {{ perl_siteprefix }}/bin/pt-variable-advisor
pt-visual-explain-binary = {{ perl_siteprefix }}/bin/pt-visual-explain
xtrabackup-binary = {{ xtrabackup_location }}/bin/xtrabackup_51
perl-binary = {{ perl_location }}/bin/perl
[logrotate]
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = {{ logrotate_location }}/usr/sbin/logrotate
gzip-binary = {{ gzip_location }}/bin/gzip
gunzip-binary = {{ gzip_location }}/bin/gunzip
# Directories
wrapper = ${rootdirectory:bin}/logrotate
conf = ${rootdirectory:etc}/logrotate.conf
logrotate-entries = ${directory:logrotate-entries}
backup = ${directory:logrotate-backup}
state-file = ${rootdirectory:srv}/logrotate.status
[logrotate-entry-mariadb] [logrotate-entry-mariadb]
<= logrotate
recipe = slapos.cookbook:logrotate.d recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
name = mariadb name = mariadb
log = ${mariadb-instance:error-log} ${mariadb-instance:slow-query-log} log = ${my-cnf-parameters:error-log} ${my-cnf-parameters:slow-query-log}
post = ${mariadb-instance:mysql-binary} --no-defaults -B --socket=${mariadb-instance:socket} -e "FLUSH LOGS" post = "${binary-wrap-mysql:wrapper-path}" -B -u root -e "FLUSH LOGS"
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ dcron_location }}/sbin/crond
cron-entries = ${directory:cron-entries}
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
binary = ${basedirectory:services}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${rootdirectory:bin}/cron_simplelogger
log = ${basedirectory:log}/cron.log
[cron-entry-logrotate]
<= cron
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
[binary-link] [binary-link]
recipe = slapos.cookbook:symbolic.link recipe = slapos.cookbook:symbolic.link
target-directory = ${rootdirectory:bin} target-directory = ${directory:bin}
link-binary = link-binary = {{ dumps(parameter_dict['link-binary']) }}
{{ coreutils_location }}/bin/basename
{{ coreutils_location }}/bin/cat
{{ coreutils_location }}/bin/cp
{{ coreutils_location }}/bin/ls
{{ coreutils_location }}/bin/tr
{{ coreutils_location }}/bin/uname
{{ gettext_location }}/lib/gettext/hostname
{{ grep_location }}/bin/grep
{{ sed_location }}/bin/sed
{{ mariadb_location }}/bin/mysql
[{{ section("binary-link-mysqlbinlog") }}]
< = binary-link
link-binary = {{ parameter_dict['mariadb-location'] }}/bin/mysqlbinlog
[binary-wrap-base]
recipe = slapos.cookbook:wrapper
# Note: --defaults-file must be the first argument, otherwise wrapped binary
# will reject it.
command-line = "{{ parameter_dict['mariadb-location'] }}/bin/${:command}" --defaults-file="${my-cnf:rendered}"
wrapper-path = ${directory:bin}/${:command}
parameters-extra = true
[binary-wrap-mysql]
< = binary-wrap-base
command = mysql
[binary-wrap-mysqldump]
< = binary-wrap-base
command = mysqldump
[binary-wrap-mysql_upgrade]
< = binary-wrap-base
command = mysql_upgrade
[binary-wrap-mysql_tzinfo_to_sql]
< = binary-wrap-base
command-line = "{{ parameter_dict['mariadb-location'] }}/bin/${:command}"
command = mysql_tzinfo_to_sql
[directory]
recipe = slapos.cookbook:mkdirectory
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
services = ${:etc}/run
promise = ${:etc}/promise
srv = ${buildout:directory}/srv
backup = ${:srv}/backup
mariadb-backup-full = ${:backup}/mariadb-full
mariadb-backup-incremental = ${:backup}/mariadb-incremental
mariadb-data = ${:srv}/mariadb
mariadb-ssl = ${:etc}/mariadb-ssl
var = ${buildout:directory}/var
log = ${:var}/log
run = ${:var}/run
[resiliency-exclude-file] [resiliency-exclude-file]
# Generate rdiff exclude file in case of resiliency # Generate rdiff exclude file in case of resiliency
recipe = collective.recipe.template recipe = collective.recipe.template
input = inline: srv/mariadb/** input = inline: srv/mariadb/**
output = ${rootdirectory:srv}/exporter.exclude output = ${directory:srv}/exporter.exclude
[resiliency-after-import-script] [resiliency-after-import-script]
# Generate after import script used by importer instance of webrunner # Generate after import script used by importer instance of webrunner
recipe = collective.recipe.template recipe = collective.recipe.template
input = {{ mariadb_resiliency_after_import_script }} input = {{ parameter_dict['mariadb-resiliency-after-import-script'] }}
output = ${rootdirectory:srv}/runner-import-restore output = ${directory:srv}/runner-import-restore
mode = 755 mode = 755
dash = {{ dash_location }}/bin/dash dash = {{ parameter_dict['dash-location'] }}/bin/dash
[rootdirectory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
var = ${buildout:directory}/var
srv = ${buildout:directory}/srv
bin = ${buildout:directory}/bin
[basedirectory]
recipe = slapos.cookbook:mkdirectory
log = ${rootdirectory:var}/log
services = ${rootdirectory:etc}/run
promise = ${rootdirectory:etc}/promise
run = ${rootdirectory:var}/run
backup = ${rootdirectory:srv}/backup
[directory]
recipe = slapos.cookbook:mkdirectory
cron-entries = ${rootdirectory:etc}/cron.d
crontabs = ${rootdirectory:etc}/crontabs
cronstamps = ${rootdirectory:etc}/cronstamps
ca-dir = ${rootdirectory:srv}/ssl
mariadb-backup-full = ${basedirectory:backup}/mariadb-full
mariadb-backup-incremental = ${basedirectory:backup}/mariadb-incremental
mariadb-data = ${rootdirectory:srv}/mariadb
logrotate-backup = ${basedirectory:backup}/logrotate
logrotate-entries = ${rootdirectory:etc}/logrotate.d
[promise] [promise]
recipe = slapos.cookbook:check_port_listening recipe = slapos.cookbook:wrapper
path = ${basedirectory:promise}/mariadb command-line = "{{ parameter_dict['bin-directory'] }}/is-local-tcp-port-opened" "${my-cnf-parameters:ip}" "${my-cnf-parameters:port}"
hostname = ${mariadb-instance:ip} wrapper-path = ${directory:promise}/mariadb
port = ${mariadb-instance:port} parameters-extra = true
[slap-parameter] [buildout]
test-database-amount = 100 extends = {{ logrotate_cfg }}
{%- endif %} parts +=
publish-mariadb-url
logrotate-entry-mariadb
binary-link
update-mysql
mysqld
resiliency-exclude-file
resiliency-after-import-script
promise
{{ part_list | join('\n ') }}
# memcached-compatible volatile cache using kumofs
# that has no limitation for key length and data size
[buildout]
parts =
publish-kumofs-connection-information
kumofs-instance
logrotate
logrotate-entry-kumofs
cron
cron-entry-logrotate
resiliency-exclude-file
promise-kumofs-server
promise-kumofs-server-listen
promise-kumofs-gateway
promise-kumofs-manager
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[publish-kumofs-connection-information]
recipe = slapos.cookbook:publishurl
url = memcached://${kumofs-instance:ip}:${kumofs-instance:gateway-port}/
[kumofs-instance]
recipe = slapos.cookbook:generic.kumofs
# Network options
ip = ${slap-network-information:local-ipv4}
manager-port = 13401
server-port = 13501
server-listen-port = 13502
# previous memcached configuration
gateway-port = 11000
# previous memcached configuration
storage-size = 64m
# Paths: Running wrappers
gateway-wrapper = ${basedirectory:services}/volatile_kumofs_gateway
manager-wrapper = ${basedirectory:services}/volatile_kumofs_manager
server-wrapper = ${basedirectory:services}/volatile_kumofs_server
# Paths: Data
data-path = *#capsiz=${:storage-size}
# Paths: Logs
kumo-gateway-log = ${basedirectory:log}/kumo-gateway.log
kumo-manager-log = ${basedirectory:log}/kumo-manager.log
kumo-server-log = ${basedirectory:log}/kumo-server.log
# Binary information
kumo-gateway-binary = {{ kumo_location }}/bin/kumo-gateway
kumo-manager-binary = {{ kumo_location }}/bin/kumo-manager
kumo-server-binary = {{ kumo_location }}/bin/kumo-server
shell-path = {{ dash_location }}/bin/dash
[logrotate-entry-kumofs]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = kumofs
log = ${kumofs-instance:kumo-gateway-log} ${kumofs-instance:kumo-manager-log}
${kumofs-instance:kumo-server-log}
# rest of parts are candidates for some generic stuff
[logrotate]
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = {{ logrotate_location }}/usr/sbin/logrotate
gzip-binary = {{ gzip_location }}/bin/gzip
gunzip-binary = {{ gzip_location }}/bin/gunzip
# Directories
wrapper = ${rootdirectory:bin}/logrotate
conf = ${rootdirectory:etc}/logrotate.conf
logrotate-entries = ${directory:logrotate-entries}
backup = ${directory:logrotate-backup}
state-file = ${rootdirectory:srv}/logrotate.status
[basedirectory]
recipe = slapos.cookbook:mkdirectory
log = ${rootdirectory:var}/log
services = ${rootdirectory:etc}/run
promise = ${rootdirectory:etc}/promise
run = ${rootdirectory:var}/run
backup = ${rootdirectory:srv}/backup
[directory]
recipe = slapos.cookbook:mkdirectory
cron-entries = ${rootdirectory:etc}/cron.d
crontabs = ${rootdirectory:etc}/crontabs
cronstamps = ${rootdirectory:etc}/cronstamps
logrotate-backup = ${basedirectory:backup}/logrotate
logrotate-entries = ${rootdirectory:etc}/logrotate.d
[rootdirectory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
var = ${buildout:directory}/var
srv = ${buildout:directory}/srv
bin = ${buildout:directory}/bin
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ dcron_location }}/sbin/crond
cron-entries = ${directory:cron-entries}
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
binary = ${basedirectory:services}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${rootdirectory:bin}/cron_simplelogger
log = ${basedirectory:log}/cron.log
[cron-entry-logrotate]
<= cron
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
[resiliency-exclude-file]
# Generate rdiff exclude file in case of resiliency
recipe = collective.recipe.template
input = inline: **
output = ${rootdirectory:srv}/exporter.exclude
# Deploy zope promises scripts
[promise-template]
recipe = slapos.cookbook:check_port_listening
hostname = ${kumofs-instance:ip}
port = ${kumofs-instance:server-listen-port}
[promise-kumofs-server]
<= promise-template
path = ${basedirectory:promise}/kumofs-server
port = ${kumofs-instance:server-port}
[promise-kumofs-server-listen]
<= promise-template
path = ${basedirectory:promise}/kumofs-server-listen
port = ${kumofs-instance:server-listen-port}
[promise-kumofs-gateway]
<= promise-template
path = ${basedirectory:promise}/kumofs-gateway
port = ${kumofs-instance:gateway-port}
[promise-kumofs-manager]
<= promise-template
path = ${basedirectory:promise}/kumofs-manager
port = ${kumofs-instance:manager-port}
{% if software_type == slap_software_type -%}
{#
Note: all port counters are pre-incremented. No idea why base port is skipped.
-#}
{% set current_zeo_port = zeo_port_base | int -%}
{% set zope_port_base = zope_port_base | int -%}
{% set zope_dummy_list = [] -%}
{% set current_apache_port = apache_port_base | int -%}
{% set current_haproxy_port = haproxy_port_base | int -%}
{% set json = json_module.loads(slapparameter_dict['json']) -%}
{% set backup_periodicity = json.get('backup-periodicity', 'daily') -%}
{% set bin_directory = parameter_dict['buildout-bin-directory'] -%}
{#
XXX: This template only supports exactly one IPv4 and one IPv6 per
partition. No more (undefined result), no less (IndexError).
-#}
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set ipv6 = (ipv6_set | list)[0] -%}
{#
BBB: erp5-ca['state'] has been configured as string by mistake. Keep this for
backward compatibility with existing automatically setup CAs.
-#}
{% set erp5_ca = json.get('erp5-ca', {
'country-code': 'ZZ',
'email': 'nobody@example.com',
'state': "('State',)",
'city': 'City',
'company': 'Company',
}) -%}
{% set site_id = json['site-id'] -%}
{% set part_list = [] -%}
{% set known_tid_storage_identifier_dict = {} -%}
{% set zodb_connection_list = [] -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% macro zope(
name,
thread_amount=1,
timerserver_interval=0,
longrequest_logger_file='',
longrequest_logger_timeout='',
longrequest_logger_interval=''
) -%}
{% set conf_name = name ~ '-conf' -%}
{% set conf_parameter_name = conf_name ~ '-param' -%}
[{{ conf_parameter_name }}]
< = zope-conf-parameter-base
pid-file = ${directory:run}/{{ name }}.pid
lock-file = ${directory:run}/{{ name }}.lock
{% do zope_dummy_list.append(None) -%}
{% set offset = zope_dummy_list | length -%}
port = {{ zope_port_base + offset }}
thread-amount = {{ thread_amount }}
{% if timerserver_interval -%}
timerserver-interval = {{ timerserver_interval }}
{% endif -%}
event-log = ${directory:log}/{{ name }}-event.log
z2-log = ${directory:log}/{{ name }}-Z2.log
[{{ conf_name }}]
< = zope-conf-base
rendered = ${directory:etc}/{{ name }}.conf
extra-context =
section parameter_dict {{ conf_parameter_name }}
[{{ section(name) }}]
< = zope-base
longrequest-logger-file = {{ longrequest_logger_file }}
longrequest-logger-timeout = {{ longrequest_logger_timeout }}
longrequest-logger-interval = {{ longrequest_logger_interval }}
wrapper = ${directory:services}/{{ name }}
configuration-file = {{ '${' ~ conf_name ~ ':rendered}' }}
port = {{ '${' ~ conf_parameter_name ~ ':port}' }}
[{{ section('logrotate-entry-' ~ name) }}]
< = logrotate-base
recipe = slapos.cookbook:logrotate.d
name = {{ name }}
log = {{ '${' ~ conf_parameter_name ~ ':event-log}' }} {{ '${' ~ conf_parameter_name ~ ':z2-log}' }}
post = {{ bin_directory }}/killpidfromfile {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} SIGUSR2
{% endmacro -%}
#############################
# Directory creation
#############################
[directory]
recipe = slapos.cookbook:mkdirectory
apache-conf = ${:etc}/apache
backup = ${:srv}/backup
bin = ${buildout:directory}/bin
ca-dir = ${:srv}/ssl
cron-entries = ${:etc}/cron.d
cronstamps = ${:etc}/cronstamps
crontabs = ${:etc}/crontabs
erp5-ca-dir = ${:srv}/erp5-ssl
etc = ${buildout:directory}/etc
instance = ${:srv}/erp5shared
instance-constraint = ${:instance}/Constraint
instance-document = ${:instance}/Document
instance-etc = ${:instance}/etc
instance-etc-package-include = ${:instance}/etc/package-include
instance-extensions = ${:instance}/Extensions
instance-import = ${:instance}/import
instance-lib = ${:instance}/lib
instance-products = ${:instance}/Products
instance-propertysheet = ${:instance}/PropertySheet
instance-tests = ${:instance}/tests
log = ${:var}/log
logrotate-backup = ${:backup}/logrotate
logrotate-entries = ${:etc}/logrotate.d
promise = ${:etc}/promise
run = ${:var}/run
services = ${:etc}/run
srv = ${buildout:directory}/srv
tidstorage = ${:srv}/tidstorage
tmp = ${buildout:directory}/tmp
var = ${buildout:directory}/var
zodb = ${:srv}/zodb
zodb-backup = ${:backup}/zodb
zodb-recovery-test = ${:srv}/zodbrecoverytest
#############################
# Binary symlinking
#############################
[binary-link]
recipe = slapos.cookbook:symbolic.link
target-directory = ${directory:bin}
link-binary =
{{ parameter_dict['coreutils'] }}/bin/basename
{{ parameter_dict['coreutils'] }}/bin/cat
{{ parameter_dict['coreutils'] }}/bin/cp
{{ parameter_dict['coreutils'] }}/bin/ls
{{ parameter_dict['coreutils'] }}/bin/tr
{{ parameter_dict['coreutils'] }}/bin/uname
{{ parameter_dict['git'] }}/bin/git
{{ parameter_dict['graphviz'] }}/bin/dot
{{ parameter_dict['grep'] }}/bin/grep
{{ parameter_dict['imagemagick'] }}/bin/convert
{{ parameter_dict['imagemagick'] }}/bin/identify
{{ parameter_dict['mariadb'] }}/bin/mysql
{{ parameter_dict['mariadb'] }}/bin/mysqldump
{{ parameter_dict['sed'] }}/bin/sed
{{ parameter_dict['tesseract'] }}/bin/tesseract
{{ parameter_dict['w3m'] }}/bin/w3m
{{ parameter_dict['openssl'] }}/bin/openssl
{{ parameter_dict['poppler'] }}/bin/pdfinfo
{{ parameter_dict['poppler'] }}/bin/pdfseparate
{{ parameter_dict['poppler'] }}/bin/pdftotext
{{ parameter_dict['poppler'] }}/bin/pdftohtml
{{ parameter_dict['poppler'] }}/bin/pdfunite
{{ parameter_dict['dmtx-utils'] }}/bin/dmtxwrite
#############################
# Resiliency
#############################
# Used for ERP5 resiliency or (more probably)
# webrunner resiliency with erp5 inside.
[resiliency-exclude-file]
# Generate rdiff exclude file in case of resiliency
recipe = collective.recipe.template
input = inline: srv/zodb/**
output = ${directory:srv}/exporter.exclude
[resiliency-after-import-script]
# Generate after import script used by importer instance of webrunner
recipe = collective.recipe.template
input = inline: #!/bin/sh
# DO NOT RUN THIS SCRIPT ON PRODUCTION INSTANCE
# OR ZODB DATA WILL BE ERASED.
# This script will restore the repozo backup to the real
# zodb location. It is launched by the clone (importer) instance of webrunner
# in the end of the import script.
# Depending on the output, it will create a file containing
# the status of the restoration (success or failure).
zodb_directory="${directory:zodb}"
zodb_backup_directory="${directory:zodb-backup}"
repozo="${tidstorage:repozo-binary}"
EXIT_CODE=0
{% for zeo_id, zeo_configuration_list in json['zeo'].iteritems() -%}
{% for zeo_slave in zeo_configuration_list -%}
storage_name="{{ zeo_slave['storage-name'] }}"
zodb_path="$storage_name.fs"
pid_file=${zeo-instance-{{ zeo_id }}:pid-path}
if [ -e "$pid_file" ]; then
pid=$(cat $pid_file) > /dev/null 2>&1
if kill -0 "$pid"; then
echo "Zeo is already running with pid $pid. Aborting."
exit 1
fi
fi
echo "Removing $zodb_path..."
echo "Restoring $storage_name into $zodb_path..."
$repozo --recover --output="$zodb_directory/$zodb_path" --repository="$zodb_backup_directory/$storage_name"
CURRENT_EXIT_CODE=$?
if [ ! "$CURRENT_EXIT_CODE"="0" ]; then
EXIT_CODE="$CURRENT_EXIT_CODE"
echo "$storage_name Backup restoration failed."
fi
{% endfor -%}
{% endfor -%}
exit $EXIT_CODE
output = ${directory:srv}/runner-import-restore
mode = 755
#############################
# CA
#############################
[cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = ${directory:ca-dir}/requests
private = ${directory:ca-dir}/private
certs = ${directory:ca-dir}/certs
newcerts = ${directory:ca-dir}/newcerts
crl = ${directory:ca-dir}/crl
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ parameter_dict['openssl'] }}/bin/openssl
ca-dir = ${directory:ca-dir}
requests-directory = ${cadirectory:requests}
wrapper = ${directory:services}/ca
ca-private = ${cadirectory:private}
ca-certs = ${cadirectory:certs}
ca-newcerts = ${cadirectory:newcerts}
ca-crl = ${cadirectory:crl}
#############################
# ERP5 CA
#############################
[erp5-cadirectory]
recipe = slapos.cookbook:mkdirectory
requests = ${directory:erp5-ca-dir}/requests
private = ${directory:erp5-ca-dir}/private
certs = ${directory:erp5-ca-dir}/certs
newcerts = ${directory:erp5-ca-dir}/newcerts
crl = ${directory:erp5-ca-dir}/crl
[erp5-certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ parameter_dict['openssl'] }}/bin/openssl
ca-dir = ${directory:erp5-ca-dir}
requests-directory = ${erp5-cadirectory:requests}
wrapper = ${directory:services}/erp5-ca
ca-private = ${erp5-cadirectory:private}
ca-certs = ${erp5-cadirectory:certs}
ca-newcerts = ${erp5-cadirectory:newcerts}
ca-crl = ${erp5-cadirectory:crl}
country-code = {{ erp5_ca['country-code'] }}
email = {{ erp5_ca['email'] }}
state = {{ erp5_ca['state'] }}
city = {{ erp5_ca['city'] }}
company = {{ erp5_ca['company'] }}
#############################
# CRON
#############################
[cron-base]
cron-entries = ${directory:cron-entries}
[cron]
< = cron-base
recipe = slapos.cookbook:cron
dcrond-binary = {{ parameter_dict['dcron'] }}/sbin/crond
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
catcher = ${cron-simplelogger:wrapper}
binary = ${directory:services}/crond
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${directory:bin}/cron_simplelogger
log = ${directory:log}/cron.log
#############################
# Logrotate
#############################
[logrotate-base]
logrotate-entries = ${directory:logrotate-entries}
backup = ${directory:logrotate-backup}
[logrotate]
< = logrotate-base
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = {{ parameter_dict['logrotate'] }}/usr/sbin/logrotate
gzip-binary = {{ parameter_dict['gzip'] }}/bin/gzip
gunzip-binary = {{ parameter_dict['gzip'] }}/bin/gunzip
# Directories
wrapper = ${directory:bin}/logrotate
conf = ${directory:etc}/logrotate.conf
state-file = ${directory:srv}/logrotate.status
[cron-entry-logrotate]
< = cron-base
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
#############################
# ERP5 bootstrap
#############################
[erp5-bootstrap]
recipe = slapos.cookbook:erp5.bootstrap
runner-path = ${directory:services}/erp5-bootstrap
mysql-url = {{ slapparameter_dict['mysql-url'] }}
zope-url = http://${zope-admin:user}:${zope-admin:password}@${zope-admin:ip}:${zope-admin:port}/{{ site_id }}
#############################
# ERP5 promise
#############################
[erp5-promise]
recipe = slapos.cookbook:erp5.promise
promise-path = ${directory:etc}/erp5promise.cfg
kumofs-url = {{ slapparameter_dict['kumofs-url'] }}
memcached-url = {{ slapparameter_dict['memcached-url'] }}
cloudooo-url = {{ slapparameter_dict['cloudooo-url'] }}
smtp-url = ${slap-parameter:smtp-url}
bt5 = ${slap-parameter:bt5}
bt5-repository-url = ${slap-parameter:bt5-repository-url}
#############################
# ZEO
#############################
[zeo-instance-entry-common]
recipe = slapos.cookbook:zeo
ip = {{ ipv4 }}
binary-path = {{ bin_directory }}/runzeo
{% for zeo_id, zeo_configuration_list in json['zeo'].iteritems() -%}
{% set current_zeo_port = current_zeo_port + 1 -%}
{% set storage_list = [] -%}
{% for zeo_slave in zeo_configuration_list -%}
{% do zodb_connection_list.append((
zeo_slave['storage-name'],
zeo_slave['mount-point'] % {'site-id': site_id},
zeo_slave['zope-cache-size'],
'zeoclient',
{
'cache-size': zeo_slave['zeo-cache-size'],
'server': ipv4 ~ ':' ~ current_zeo_port,
'storage': zeo_slave['storage-name'],
'name': zeo_slave['storage-name'],
},
)) -%}
{% set zodb_path = '${directory:zodb}/' ~ zeo_slave['storage-name'] ~ '.fs' -%}
{% do storage_list.append('storage-name=%(storage-name)s zodb-path=%(zodb-path)s' % {'zodb-path': zodb_path, 'storage-name': zeo_slave['storage-name']}) -%}
{% do known_tid_storage_identifier_dict.__setitem__("((('${zeo-instance-%(zeo_id)s:ip}', ${zeo-instance-%(zeo_id)s:port}),), '%(storage_name)s')" % {
'zeo_id': zeo_id,
'storage_name': zeo_slave['storage-name']
}, (zodb_path, '${directory:zodb-backup}/%s/' % zeo_slave['storage-name'], zeo_slave['serialize-path'] % {'site-id': site_id})) -%}
{% endfor -%}
[{{ section('zeo-instance-%s' % zeo_id) }}]
< = zeo-instance-entry-common
log-path = ${directory:log}/zeo-{{ zeo_id }}.log
pid-path = ${directory:run}/zeo-{{ zeo_id }}.pid
conf-path = ${directory:etc}/zeo-{{ zeo_id }}.conf
port = {{ current_zeo_port }}
storage =
{{ storage_list | join('\n ') }}
wrapper-path = ${directory:services}/zeo-{{ zeo_id }}
[{{ section('logrotate-entry-zeo-%s' % zeo_id) }}]
< = logrotate-base
recipe = slapos.cookbook:logrotate.d
name = zeo-{{ zeo_id }}
log = ${zeo-instance-{{ zeo_id }}:log-path}
post = {{ bin_directory }}/killpidfromfile ${zeo-instance-{{ zeo_id }}:pid-path} SIGUSR2
{% endfor -%}
#############################
# Zope
#############################
[zope-base]
recipe = slapos.cookbook:generic.zope.zeo.client
user = zope
ip = {{ ipv4 }}
timezone = {{ json['timezone'] }}
tidstorage-ip = ${tidstorage:ip}
tidstorage-port = ${tidstorage:port}
instance-etc = ${directory:instance-etc}
bt5-repository = ${directory:var}/bt5_repository
tmp-path = ${directory:tmp}
bin-path = ${directory:bin}
site-zcml = ${:instance-etc}/site.zcml
inituser = ${directory:instance}/inituser
runzope-binary = {{ bin_directory }}/runzope
bt5-repository-list =
[deadlock-debugger-password]
recipe = slapos.cookbook:generate.password
[zope-conf-parameter-base]
ip = {{ ipv4 }}
site-id = {{ site_id }}
zodb-list = {{ dumps(zodb_connection_list) }}
[zope-conf-base]
recipe = slapos.recipe.template:jinja2
template = {{ parameter_dict['zope-conf-template'] }}
extra-context =
context =
key instance directory:instance
key instance_products directory:instance-products
raw deadlock_path /manage_debug_threads
key deadlock_debugger_password deadlock-debugger-password:passwd
key tidstorage_ip tidstorage:ip
key tidstorage_port tidstorage:port
key promise_path erp5-promise:promise-path
${:extra-context}
# Distribution node
{{ zope('zope-distribution', timerserver_interval=1) }}
# Admin node
{{ zope('zope-admin') }}
# Activity nodes
{% for q in range(1, json['activity']['zopecount'] + 1) -%}
{{ zope('zope-activity-%s' % q, timerserver_interval=1) }}
{%- endfor %}
# Other zopes, apaches and haproxies
{% set publish_url_list = [] -%}
{% for backend_name, backend_configuration in json['backend'].iteritems() -%}
{% set haproxy_backend_list = [] -%}
{% set longrequest_logger = backend_configuration.get('longrequest-logger') -%}
{% for q in range(1, backend_configuration['zopecount'] + 1) -%}
{% set part_name = 'zope-%s-%s' % (backend_name, q) -%}
{% if longrequest_logger != None -%}
{% set longrequest_logger_file = '${directory:log}/%s-longrequest.log' % (part_name, ) -%}
{% set longrequest_logger_timeout = longrequest_logger.get('timeout', '4') -%}
{% set longrequest_logger_interval = longrequest_logger.get('interval', '2') -%}
{% else -%}
{% set longrequest_logger_file = '' -%}
{% set longrequest_logger_timeout = '' -%}
{% set longrequest_logger_interval = '' -%}
{% endif -%}
{{ zope(
part_name,
thread_amount=backend_configuration['thread-amount'],
longrequest_logger_file=longrequest_logger_file,
longrequest_logger_timeout=longrequest_logger_timeout,
longrequest_logger_interval=longrequest_logger_interval,
) }}
{% do haproxy_backend_list.append('${%(part_name)s:ip}:${%(part_name)s:port}' % {'part_name': part_name}) -%}
{% endfor -%}
{% set scheme = backend_configuration.get('scheme', ['https']) -%}
{% set current_apache_port = current_apache_port + 2 -%}
{% set current_haproxy_port = current_haproxy_port + 1 -%}
{% if 'http' in scheme -%}
{% set section_name = 'apache-public-' ~ backend_name -%}
{% do publish_url_list.append(
'url-public-%(backend_name)s = http://[${%(section_name)s:ip}]:${%(section_name)s:port}' % {
'backend_name': backend_name,
'section_name': section_name,
}) -%}
[{{ section(section_name) }}]
recipe = slapos.cookbook:apache.zope.backend
backend = http://${haproxy-{{ backend_name }}:ip}:${haproxy-{{ backend_name }}:port}
ip = {{ ipv6 }}
port = {{ current_apache_port }}
scheme = http
wrapper = ${directory:services}/apache-public-{{ backend_name }}
configuration-file = ${directory:apache-conf}/apache-public-{{ backend_name }}.conf
access-control-string = {{ backend_configuration['access-control-string'] }}
pid-file = ${directory:run}/apache-public-{{ backend_name }}.pid
lock-file = ${directory:run}/apache-public-{{ backend_name }}.lock
error-log = ${directory:log}/apache-public-{{ backend_name }}-error.log
access-log = ${directory:log}/apache-public-{{ backend_name }}-access.log
apache-binary = {{ parameter_dict['apache'] }}/bin/httpd
[{{ section('logrotate-entry-apache-public-' ~ backend_name) }}]
< = logrotate-base
recipe = slapos.cookbook:logrotate.d
name = apache-public-{{ backend_name }}
log = ${apache-public-{{ backend_name }}:error-log} ${apache-public-{{ backend_name }}:access-log}
post = {{ bin_directory }}/killpidfromfile ${apache-public-{{ backend_name }}:pid-file} SIGUSR1
{% endif -%}
{% if 'https' in scheme -%}
{% set section_name = 'apache-' ~ backend_name -%}
{% do publish_url_list.append(
'url-%(backend_name)s = https://[${%(section_name)s:ip}]:${%(section_name)s:port}' % {
'backend_name': backend_name,
'section_name': section_name,
}) -%}
[{{ section(section_name) }}]
recipe = slapos.cookbook:apache.zope.backend
backend = http://${haproxy-{{ backend_name }}:ip}:${haproxy-{{ backend_name }}:port}
ip = {{ ipv6 }}
port = {{ current_apache_port - 1 }}
wrapper = ${directory:bin}/apache-{{ backend_name }}
scheme = https
key-file = ${directory:apache-conf}/apache-{{ backend_name }}.key
cert-file = ${directory:apache-conf}/apache-{{ backend_name }}.crt
configuration-file = ${directory:apache-conf}/apache-{{ backend_name }}.conf
access-control-string = {{ backend_configuration['access-control-string'] }}
pid-file = ${directory:run}/apache-{{ backend_name }}.pid
lock-file = ${directory:run}/apache-{{ backend_name }}.lock
ssl-session-cache = $${directory:log}/apache-ssl-session-cache
error-log = ${directory:log}/apache-{{ backend_name }}-error.log
access-log = ${directory:log}/apache-{{ backend_name }}-access.log
apache-binary = {{ parameter_dict['apache'] }}/bin/httpd
ssl-authentication = {{ backend_configuration.get('ssl-authentication', False) }}
backend-path = {{ backend_configuration.get('backend-path', '/') % {'site-id': site_id} }}
# Note: Without erp5-certificate-authority main certificate have to be hardcoded
ssl-authentication-certificate = ${erp5-certificate-authority:ca-dir}/cacert.pem
ssl-authentication-crl = ${erp5-certificate-authority:ca-crl}
[{{ section('ca-apache-' ~ backend_name) }}]
< = certificate-authority
recipe = slapos.cookbook:certificate_authority.request
key-file = ${apache-{{ backend_name }}:key-file}
cert-file = ${apache-{{ backend_name }}:cert-file}
executable = ${apache-{{ backend_name }}:wrapper}
wrapper = ${directory:services}/apache-{{ backend_name }}
[{{ section('logrotate-entry-apache-' ~ backend_name) }}]
< = logrotate-base
recipe = slapos.cookbook:logrotate.d
name = apache-{{ backend_name }}
log = ${apache-{{ backend_name }}:error-log} ${apache-{{ backend_name }}:access-log}
post = {{ bin_directory }}/killpidfromfile ${apache-{{ backend_name }}:pid-file} SIGUSR1
[{{ section('haproxy-' ~ backend_name) }}]
recipe = slapos.cookbook:haproxy
name = {{ backend_name }}
conf-path = ${directory:etc}/haproxy-{{ backend_name }}.cfg
socket-path = ${directory:run}/haproxy-{{ backend_name }}.sock
ip = {{ ipv4 }}
port = {{ current_haproxy_port }}
maxconn = {{ backend_configuration['maxconn'] }}
server-check-path = /{{ site_id }}/getId
wrapper-path = ${directory:services}/haproxy-{{ backend_name }}
binary-path = {{ parameter_dict['haproxy'] }}/sbin/haproxy
ctl-path = ${directory:bin}/haproxy-{{ backend_name }}-ctl
backend-list = {{ haproxy_backend_list | join(' ')}}
{%- endif %}
{% endfor -%}
[{{ section('publish-apache-backend-list') }}]
recipe = slapos.cookbook:publish
{{ publish_url_list | join('\n') }}
#############################
# tidstorage
#############################
[tidstorage]
recipe = slapos.cookbook:tidstorage
known-tid-storage-identifier-dict = {{ known_tid_storage_identifier_dict }}
configuration-path = ${directory:etc}/tidstorage.py
ip = {{ ipv4 }}
port = 6001
timestamp-file-path = ${directory:tidstorage}/repozo_tidstorage_timestamp.log
logfile-name = ${directory:log}/tidstorage.log
pidfile-name = ${directory:run}/tidstorage.pid
status-file = ${directory:tidstorage}/tidstorage.tid
tidstorage-repozo-binary = {{ bin_directory }}/tidstorage_repozo
tidstoraged-binary = {{ bin_directory }}/tidstoraged
repozo-binary = {{ bin_directory }}/repozo
tidstorage-wrapper = ${directory:services}/tidstoraged
repozo-wrapper = ${buildout:bin-directory}/tidstorage-repozo
[cron-entry-tidstorage-backup]
< = cron-base
recipe = slapos.cookbook:cron.d
name = tidstorage
frequency = {{ backup_periodicity }}
command = ${tidstorage:repozo-wrapper}
[logrotate-entry-tidstorage]
< = logrotate-base
recipe = slapos.cookbook:logrotate.d
name = tidstorage
log = ${tidstorage:logfile-name}
post = {{ bin_directory }}/killpidfromfile ${tidstorage:pidfile-name} SIGHUP
#############################
# buildout main section
#############################
[buildout]
parts =
logrotate
cron
cron-entry-logrotate
certificate-authority
erp5-certificate-authority
resiliency-exclude-file
resiliency-after-import-script
tidstorage
cron-entry-tidstorage-backup
logrotate-entry-tidstorage
binary-link
erp5-promise
erp5-bootstrap
{{ part_list | join('\n ') }}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
{%- endif %}
{% if software_type == slap_software_type -%}
{% set web_checker_parameter = slapparameter_dict['web-checker-mail-address'] -%}
[buildout]
parts =
publish-varnish-connection-information
varnish-instance
cron
cron-entry-logrotate
resiliency-exclude-file
{# When web_checker related parameter is given, web_checker will be enabled.#}
{% if web_checker_parameter is defined %}
web-checker
cron-entry-web-checker
logrotate-entry-web-checker
{% endif %}
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[publish-varnish-connection-information]
recipe = slapos.cookbook:publishurl
url = http://${varnish-instance:ip}:${varnish-instance:server-port}/
[varnish-instance]
recipe = slapos.cookbook:generic.varnish
# Network options
ip = ${slap-network-information:local-ipv4}
server-port = 6001
manager-port = 6002
stunnel-port = 6003
# Paths: Running wrappers
varnishd-wrapper = ${basedirectory:services}/varnishd
varnishlog-wrapper = ${rootdirectory:bin}/varnishlog
stunnel-wrapper = ${basedirectory:services}/stunnel
# Binary information
varnishd-binary = {{ parameter_dict['varnish'] }}/sbin/varnishd
varnishlog-binary = {{ parameter_dict['varnish'] }}/bin/varnishlog
shell-path = {{ parameter_dict['dash'] }}/bin/dash
stunnel-binary = {{ parameter_dict['stunnel'] }}/bin/stunnel
# Configuration by VCL
vcl-file = ${rootdirectory:etc}/default.vcl
pid-file = ${basedirectory:run}/varnishd.pid
stunnel-conf-file = ${rootdirectory:etc}/stunnel.conf
stunnel-pid-file = ${basedirectory:run}/stunnel.pid
varnish-data = ${directory:varnish-data}
# this will pass at -n option
varnish-instance-name = ${directory:varnish-instance}
web-checker = {{ parameter_dict['buildout-bin-directory'] }}/web_checker_utility
[cron-entry-web-checker]
<= cron
recipe = slapos.cookbook:cron.d
name = web-checker
frequency = 0 0 * * *
command = ${varnish-instance:web-checker} ${web-checker:web-checker-config}
[web-checker]
recipe = slapos.cookbook:webchecker
web-checker-config = ${rootdirectory:etc}/web_checker.cfg
web-checker-working-directory = ${directory:web-checker}
frontend-url = ${varnish-instance:ip}:${varnish-instance:server-port}
wget-binary-path = {{ parameter_dict['wget'] }}/bin/wget
varnishlog-binary-path = ${varnish-instance:varnishlog-wrapper}
web-checker-log = ${basedirectory:log}/web-checker.log
[cron]
recipe = slapos.cookbook:cron
dcrond-binary = {{ parameter_dict['dcron'] }}/sbin/crond
cron-entries = ${directory:cron-entries}
crontabs = ${directory:crontabs}
cronstamps = ${directory:cronstamps}
binary = ${basedirectory:services}/crond
catcher = ${cron-simplelogger:wrapper}
[cron-simplelogger]
recipe = slapos.cookbook:simplelogger
wrapper = ${rootdirectory:bin}/cron_simplelogger
log = ${basedirectory:log}/cron.log
[cron-entry-logrotate]
<= cron
recipe = slapos.cookbook:cron.d
name = logrotate
frequency = 0 0 * * *
command = ${logrotate:wrapper}
[logrotate]
recipe = slapos.cookbook:logrotate
# Binaries
logrotate-binary = {{ parameter_dict['logrotate'] }}/usr/sbin/logrotate
gzip-binary = {{ parameter_dict['gzip'] }}/bin/gzip
gunzip-binary = {{ parameter_dict['gzip'] }}/bin/gunzip
# Directories
wrapper = ${rootdirectory:bin}/logrotate
conf = ${rootdirectory:etc}/logrotate.conf
logrotate-entries = ${directory:logrotate-entries}
backup = ${directory:logrotate-backup}
state-file = ${rootdirectory:srv}/logrotate.status
[logrotate-entry-web-checker]
<= logrotate
recipe = slapos.cookbook:logrotate.d
name = web-checker
log = ${web-checker:web-checker-log}
frequency = daily
rotate-num = 30
sharedscripts = true
notifempty = true
create = true
[resiliency-exclude-file]
# Generate rdiff exclude file in case of resiliency
recipe = collective.recipe.template
input = inline: **
output = ${rootdirectory:srv}/exporter.exclude
[basedirectory]
recipe = slapos.cookbook:mkdirectory
services = ${rootdirectory:etc}/run
run = ${rootdirectory:var}/run
backup = ${rootdirectory:srv}/backup
log = ${rootdirectory:var}/log
backup = ${rootdirectory:srv}/backup
[directory]
recipe = slapos.cookbook:mkdirectory
varnish-data = ${rootdirectory:srv}/varnish
varnish-instance = ${directory:varnish-data}/instance
cron-entries = ${rootdirectory:etc}/cron.d
crontabs = ${rootdirectory:etc}/crontabs
cronstamps = ${rootdirectory:etc}/cronstamps
logrotate-backup = ${basedirectory:backup}/logrotate
logrotate-entries = ${rootdirectory:etc}/logrotate.d
web-checker = ${rootdirectory:srv}/web-checker
[rootdirectory]
recipe = slapos.cookbook:mkdirectory
etc = ${buildout:directory}/etc
var = ${buildout:directory}/var
srv = ${buildout:directory}/srv
bin = ${buildout:directory}/bin
{% endif %}
{% set next_port = slapparameter_dict['tcpv4-port'] -%}
{% set ipv4 = (ipv4_set | list)[0] -%}
{% set backup_periodicity = slapparameter_dict.get('backup-periodicity', 'daily') -%}
{% set part_list = [] -%}
{% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
{% set storage_dict = {} -%}
{% set default_zodb_path = buildout_directory ~ '/srv/zodb' -%}
{% set default_backup_path = buildout_directory ~ '/srv/backup/zodb' -%}
{% set bin_directory = parameter_dict['buildout-bin-directory'] -%}
[logrotate-base]
recipe = slapos.cookbook:logrotate.d
logrotate-entries = ${logrotate:logrotate-entries}
backup = ${logrotate:backup}
[zeo-base]
recipe = slapos.cookbook:zeo
log-path = ${directory:log}/${:base-name}.log
pid-path = ${directory:run}/${:base-name}.pid
conf-path = ${directory:etc}/${:base-name}.conf
wrapper-path = ${directory:services}/${:base-name}
binary-path = {{ bin_directory }}/runzeo
ip = {{ ipv4 }}
{% set known_tid_storage_identifier_dict = {} -%}
{% set zodb_dict = {} -%}
{% for name, zodb in slapparameter_dict['zodb-dict'].iteritems() -%}
{% do zodb_dict.setdefault(zodb.get('family', 'default').lower(), []).append((name, zodb)) -%}
{% endfor -%}
{% set tidstorage_port = next_port + len(zodb_dict) -%}
{% for family, zodb in zodb_dict.iteritems() -%}
{% set storage_list = [] -%}
{% set known_tid_storage_identifier_host = (ipv4, next_port), -%}
{% for name, zodb in zodb -%}
{% do storage_dict.__setitem__(name, {'server': ipv4 ~ ':' ~ next_port, 'storage': name}) %}
{% set path = zodb.get('path', '%(zodb)s/%(name)s.fs') % {'zodb': default_zodb_path, 'name': name} -%}
{% do storage_list.append((name, path)) -%}
{% set backup_directory = zodb.get('backup', '%(backup)s/%(name)s') % {'backup': default_backup_path, 'name': name} -%}
{# BBB: No mount-point specified because they're meaningless for ZEO and
TIDStorage. Pass '' for compatibility, and not None
because this would disable TIDStorage bootstrapping. -#}
{% do known_tid_storage_identifier_dict.__setitem__(json_module.dumps(
(known_tid_storage_identifier_host, name)),
(path, backup_directory, '')) -%}
{% endfor -%}
{% set zeo_section_name = 'zeo-' ~ family %}
[{{ zeo_section_name }}]
< = zeo-base
base-name = zeo-{{ family }}
port = {{ next_port }}
storage = {{ dumps(storage_list) }}
[{{ section("logrotate-" ~ zeo_section_name) }}]
< = logrotate-base
name = {{ "${" ~ zeo_section_name ~ ":base-name}" }}
log = {{ "${" ~ zeo_section_name ~ ":log-path}" }}
post = {{ bin_directory }}/slapos-kill --pidfile {{ "${" ~ zeo_section_name ~ ":pid-path}" }} -s USR2
[{{ section(zeo_section_name ~ "-promise") }}]
recipe = slapos.cookbook:check_port_listening
hostname = {{ "${" ~ zeo_section_name ~ ":ip}" }}
port = {{ "${" ~ zeo_section_name ~ ":port}" }}
path = ${directory:promises}/zeo-{{ family }}
{% set next_port = next_port + 1 -%}
{% endfor -%}
{% if backup_periodicity == 'never' -%}
{% set known_tid_storage_identifier_dict = () %}
{% set tidstorage_repozo_path = '' -%}
{% else -%}
[tidstorage]
recipe = slapos.cookbook:tidstorage
known-tid-storage-identifier-dict = {{ dumps(known_tid_storage_identifier_dict) }}
configuration-path = ${directory:etc}/tidstorage.py
ip = {{ ipv4 }}
port = {{ tidstorage_port }}
{% set tidstorage_repozo_path = slapparameter_dict.get('tidstorage-repozo-path', buildout_directory ~ '/srv/backup/tidstorage') -%}
timestamp-file-path = {{ tidstorage_repozo_path ~ '/repozo_tidstorage_timestamp.log' }}
{# BBB: recipe requires logfile-name for nothing because tidstorage runs in foreground mode -#}
logfile-name =
pidfile-name = ${directory:run}/tidstorage.pid
{# TODO: Add support for backup status file, so that the status file can be close to the ZODB (rather than close to the backup files). And do it efficiently, to not copy the whole status file every time. -#}
status-file = {{ tidstorage_repozo_path ~ '/tidstorage.tid' }}
tidstorage-repozo-binary = {{ bin_directory }}/tidstorage_repozo
tidstoraged-binary = {{ bin_directory }}/tidstoraged
repozo-binary = {{ bin_directory }}/repozo
repozo-wrapper = ${buildout:bin-directory}/tidstorage-repozo
{% if len(known_tid_storage_identifier_dict) > 1 -%}
tidstorage-wrapper = ${directory:services}/tidstoraged
[{{ section("promise-tidstorage") }}]
recipe = slapos.cookbook:check_port_listening
hostname = ${tidstorage:ip}
port = ${tidstorage:port}
path = ${directory:promises}/tidstorage
{% endif -%}
[{{ section("cron-entry-tidstorage-backup") }}]
# TODO:
# - configurable full/incremental
# - configurable retention
recipe = slapos.cookbook:cron.d
cron-entries = ${cron:cron-entries}
name = tidstorage
time = {{ dumps(backup_periodicity) }}
command = ${tidstorage:repozo-wrapper}
{% endif -%}
[publish]
recipe = slapos.cookbook:publish.serialised
storage-dict = {{ dumps(storage_dict) }}
{% if len(known_tid_storage_identifier_dict) > 1 -%}
tidstorage-ip = ${tidstorage:ip}
tidstorage-port = ${tidstorage:port}
{% else -%}
tidstorage-ip =
tidstorage-port =
{% endif -%}
# Used for ERP5 resiliency or (more probably)
# webrunner resiliency with erp5 inside.
[{{ section("resiliency-exclude-file") }}]
# Generate rdiff exclude file
recipe = collective.recipe.template
input = inline: {{ default_zodb_path }}/**
output = ${directory:srv}/exporter.exclude
[{{ section("resiliency-after-import-script") }}]
# Generate after import script used by importer instance of webrunner
recipe = collective.recipe.template
input = inline: #!/bin/sh
# DO NOT RUN THIS SCRIPT ON PRODUCTION INSTANCE
# OR ZODB DATA WILL BE ERASED.
# This script will restore the repozo backup to the real
# zodb location. It is launched by the clone (importer) instance of webrunner
# in the end of the import script.
# Depending on the output, it will create a file containing
# the status of the restoration (success or failure).
zodb_directory="${directory:zodb}"
zodb_backup_directory="{{ default_backup_path }}"
repozo="${tidstorage:repozo-binary}"
EXIT_CODE=0
{% for family, zodb in zodb_dict.iteritems() -%}
{% for name, zodb in zodb -%}
{% set zeo_section_name = 'zeo-' ~ family %}
storage_name="{{ name }}"
zodb_path="$storage_name.fs"
pid_file={{ "${" ~ zeo_section_name ~ ":pid-path}" }}
if [ -e "$pid_file" ]; then
pid=$(cat $pid_file) > /dev/null 2>&1
if kill -0 "$pid"; then
echo "Zeo is already running with pid $pid. Aborting."
exit 1
fi
fi
echo "Removing $zodb_path..."
echo "Restoring $storage_name into $zodb_path..."
$repozo --recover --output="$zodb_directory/$zodb_path" --repository="$zodb_backup_directory/$storage_name"
CURRENT_EXIT_CODE=$?
if [ ! "$CURRENT_EXIT_CODE"="0" ]; then
EXIT_CODE="$CURRENT_EXIT_CODE"
echo "$storage_name Backup restoration failed."
fi
{% endfor -%}
{% endfor -%}
exit $EXIT_CODE
output = ${directory:srv}/runner-import-restore
mode = 755
[directory]
recipe = slapos.cookbook:mkdirectory
bin = ${buildout:directory}/bin
etc = ${buildout:directory}/etc
services = ${:etc}/run
promises = ${:etc}/promise
srv = ${buildout:directory}/srv
var = ${buildout:directory}/var
log = ${:var}/log
run = ${:var}/run
backup-zodb = {{ default_backup_path }}
zodb = {{ default_zodb_path }}
tidstorage = {{ tidstorage_repozo_path }}
[buildout]
extends = {{ logrotate_cfg }}
parts +=
{{ part_list | join('\n ') }}
publish
[buildout] {% set use_ipv6 = slapparameter_dict.get('use-ipv6', False) -%}
parts = {% set next_port = slapparameter_dict['port-base'] -%}
certificate-authority {% set site_id = slapparameter_dict['site-id'] -%}
publish-apache-zope-backend-connection-string {% set zodb_dict = slapparameter_dict['zodb-dict'] -%}
zope-instance {% set node_id_base = slapparameter_dict['name'] -%}
apache-zope-backend-instance {% set part_list = [] -%}
ca-apache-zope-backend {% set publish_list = [] -%}
logrotate {% set longrequest_logger_base_path = buildout_directory ~ '/var/log/longrequest_logger_' -%}
erp5-certificate-authority {% macro section(name) %}{% do part_list.append(name) %}{{ name }}{% endmacro -%}
logrotate-entry-zope {% set bin_directory = parameter_dict['buildout-bin-directory'] -%}
cron {#
cron-entry-logrotate XXX: This template only supports exactly one IPv4 and one IPv6 per
binary-link partition. No more (undefined result), no less (IndexError).
bt5-erp5-link -#}
promise-zope {% set ipv4 = (ipv4_set | list)[0] -%}
promise-apache-zope-backend
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
versions = versions
{% if 'frontend-software-url' in slapparameter_dict -%} {% if slapparameter_dict['mysql-test-url-list'] -%}
[request-slave-frontend] [{{ section('test-runner') }}]
recipe = slapos.cookbook:request recipe = slapos.cookbook:erp5.test
software-url = {{ slapparameter_dict['frontend-software-url'] }} certificate-authority-path = ${test-certificate-authority:ca-dir}
software-type = {{ slapparameter_dict.get('frontend-software-type', 'RootSoftwareInstance') }} mysql-url-list = {{ dumps(slapparameter_dict['mysql-test-url-list']) }}
sla-instance_guid = {{ slapparameter_dict['frontend-instance-guid'] }} kumofs-url = {{ dumps(slapparameter_dict['kumofs-url']) }}
server-url = ${slap-connection:server-url} memcached-url = {{ dumps(slapparameter_dict['memcached-url']) }}
key-file = ${slap-connection:key-file} cloudooo-url = {{ dumps(slapparameter_dict['cloudooo-url']) }}
cert-file = ${slap-connection:cert-file} test-instance-path = ${directory:unit-test-path}
computer-id = ${slap-connection:computer-id} prepend-path = ${buildout:bin-directory}
partition-id = ${slap-connection:partition-id} run-unit-test = ${buildout:bin-directory}/runUnitTest
name = SlaveFrontend run-test-suite = ${buildout:bin-directory}/runTestSuite
slave = true openssl-binary = ${test-certificate-authority:openssl-binary}
{% set config_dict = { run-unit-test-binary = {{ parameter_dict['bin-directory'] }}/runUnitTest
'url': '${apache-zope-backend-instance:scheme}://[${apache-zope-backend-instance:ip}]:${apache-zope-backend-instance:port}', run-test-suite-binary = {{ parameter_dict['bin-directory'] }}/runTestSuite
'type': 'zope',
} -%}
{% if 'frontend-domain' in slapparameter_dict -%}
{% do config_dict.__setitem__('custom_domain', slapparameter_dict['frontend-domain']) -%}
{% endif -%}
{% for name, value in config_dict.items() -%}
config-{{ name }} = {{ value }}
{% endfor -%}
return = site_url
[publish-apache-zope-backend-connection-string] [test-certificate-authority]
recipe = slapos.cookbook:publish recipe = slapos.cookbook:certificate_authority
url = ${request-slave-frontend:connection-site_url} openssl-binary = ${binary-link:target-directory}/openssl
login = ${zope-instance:user} ca-dir = ${directory:test-ca-dir}
password = ${zope-instance:password} requests-directory = ${directory:test-ca-requests}
url-deadlock = ${:url}/${zope-instance:deadlock-path}?${zope-instance:deadlock-password} wrapper = ${directory:services}/test-ca
{% else %} ca-private = ${directory:test-ca-private}
[publish-apache-zope-backend-connection-string] ca-certs = ${directory:test-ca-certs}
recipe = slapos.cookbook:publish ca-newcerts = ${directory:test-ca-newcerts}
url = https://${zope-instance:user}:${zope-instance:password}@[${apache-zope-backend-instance:ip}]:${apache-zope-backend-instance:port} ca-crl = ${directory:test-ca-crl}
url-deadlock = ${:url}/${zope-instance:deadlock-path}?${zope-instance:deadlock-password} {%- endif %}
{% endif %}
[apache-zope-backend-instance] [directory]
recipe = slapos.cookbook:apache.zope.backend recipe = slapos.cookbook:mkdirectory
backend = http://${zope-instance:ip}:${zope-instance:port}/ bin = ${buildout:directory}/bin
ip = ${slap-network-information:global-ipv6} etc = ${buildout:directory}/etc
port = 16001 instance = ${:srv}/erp5shared
wrapper = ${rootdirectory:bin}/apache instance-constraint = ${:instance}/Constraint
key-file = ${directory:apache-conf}/apache.key instance-document = ${:instance}/Document
cert-file = ${directory:apache-conf}/apache.crt instance-etc = ${:instance}/etc
configuration-file = ${directory:apache-conf}/apache.conf instance-etc-package-include = ${:instance}/etc/package-include
{# By default, if no white list is specified, backend allows access to everyone -#} instance-extensions = ${:instance}/Extensions
access-control-string = {{ slapparameter_dict.get('access-control-string', 'all') }} instance-import = ${:instance}/import
pid-file = ${basedirectory:run}/apache.pid instance-lib = ${:instance}/lib
lock-file = ${basedirectory:run}/apache.lock instance-products = ${:instance}/Products
ssl-session-cache = ${basedirectory:log}/apache-ssl-session-cache instance-propertysheet = ${:instance}/PropertySheet
error-log = ${basedirectory:log}/apache-error.log instance-tests = ${:instance}/tests
access-log = ${basedirectory:log}/apache-access.log log = ${:var}/log
apache-binary = {{ apache_location }}/bin/httpd run = ${:var}/run
scheme = https services = ${:etc}/run
srv = ${buildout:directory}/srv
tmp = ${buildout:directory}/tmp
var = ${buildout:directory}/var
promises = ${:etc}/promise
unit-test-path = ${:srv}/test-instance/unit_test
test-ca-dir = ${:srv}/test-ca
test-ca-requests = ${:test-ca-dir}/requests
test-ca-private = ${:test-ca-dir}/private
test-ca-certs = ${:test-ca-dir}/certs
test-ca-newcerts = ${:test-ca-dir}/newcerts
test-ca-crl = ${:test-ca-dir}/crl
ca-dir = ${:srv}/ca
ca-requests = ${:ca-dir}/requests
ca-private = ${:ca-dir}/private
ca-certs = ${:ca-dir}/certs
ca-newcerts = ${:ca-dir}/newcerts
ca-crl = ${:ca-dir}/crl
[ca-apache-zope-backend] [binary-link]
<= certificate-authority recipe = slapos.cookbook:symbolic.link
recipe = slapos.cookbook:certificate_authority.request target-directory = ${directory:bin}
key-file = ${apache-zope-backend-instance:key-file} link-binary = {{ dumps(parameter_dict['link-binary']) }}
cert-file = ${apache-zope-backend-instance:cert-file}
executable = ${apache-zope-backend-instance:wrapper}
wrapper = ${basedirectory:services}/apache
[zope-instance] [certificate-authority-common]
recipe = slapos.cookbook:generic.zope requests-directory = ${directory:ca-requests}
ca-dir = ${directory:ca-dir}
ca-private = ${directory:ca-private}
ca-certs = ${directory:ca-certs}
ca-newcerts = ${directory:ca-newcerts}
ca-crl = ${directory:ca-crl}
# Options [{{ section('certificate-authority') }}]
user = zope < = certificate-authority-common
port = 12001 recipe = slapos.cookbook:certificate_authority
ip = ${slap-network-information:local-ipv4} openssl-binary = ${binary-link:target-directory}/openssl
zodb-cache-size = 5000 wrapper = ${directory:services}/ca
thread-amount = 4
zodb-path = ${directory:zodb}/main.fs
deadlock-path = /manage_debug_threads
# Paths {% if use_ipv6 -%}
wrapper = ${basedirectory:services}/zope-development {% set ipv6 = (ipv6_set | list)[0] -%}
instance-path = ${directory:instance}
instance-etc = ${directory:instance-etc}
instance-products = ${directory:instance-products}
bt5-repository = ${rootdirectory:var}/bt5_repository
tmp-path = ${rootdirectory:tmp}
bin-path = ${rootdirectory:bin}
site-zcml = ${:instance-etc}/site.zcml
logrotate-post = ${rootdirectory:bin}/zope-post-logrotate
pid-file = ${basedirectory:run}/zope.pid
lock-file = ${basedirectory:run}/zope.lock
event-log = ${basedirectory:log}/zope-event.log
z2-log = ${basedirectory:log}/zope-Z2.log
configuration-file = ${rootdirectory:etc}/zope.conf
inituser = ${:instance-path}/inituser
# Binary information
runzope-binary = {{ bin_directory }}/runzope
# Defaults [ipv6toipv4-base]
bt5-repository-list = recipe = slapos.cookbook:ipv6toipv4
runner-path = ${directory:services}/${:base-name}
6tunnel-path = {{ parameter_dict['6tunnel'] }}/bin/6tunnel
shell-path = {{ parameter_dict['dash'] }}/bin/dash
ipv4 = {{ ipv4 }}
ipv6 = {{ ipv6 }}
{% endif -%}
[logrotate] {% set hosts_dict = {} -%}
recipe = slapos.cookbook:logrotate {% for alias, url in (
# Binaries ('erp5-memcached-volatile', slapparameter_dict['memcached-url']),
logrotate-binary = {{ logrotate_location }}/usr/sbin/logrotate ('erp5-memcached-persistent', slapparameter_dict['kumofs-url']),
gzip-binary = {{ gzip_location }}/bin/gzip ('erp5-cloudooo', slapparameter_dict['cloudooo-url']),
gunzip-binary = {{ gzip_location }}/bin/gunzip ) -%}
# Directories {% do hosts_dict.__setitem__(
wrapper = ${rootdirectory:bin}/logrotate alias,
conf = ${rootdirectory:etc}/logrotate.conf urlparse.urlparse(url).hostname,
logrotate-entries = ${directory:logrotate-entries} ) -%}
backup = ${directory:logrotate-backup} {%- endfor %}
state-file = ${rootdirectory:srv}/logrotate.status {% for i, url in enumerate(slapparameter_dict['mysql-url-list']) -%}
{% do hosts_dict.__setitem__(
'erp5-catalog-' ~ i,
urlparse.urlparse(url).hostname,
) -%}
{%- endfor %}
{% do hosts_dict.update(slapparameter_dict['hosts-dict']) -%}
[host-common]
[logrotate-entry-zope] [hosts-parameter]
<= logrotate # Used for both hosts and hostaliases sections.
recipe = slapos.cookbook:logrotate.d host-dict = {{ dumps(hosts_dict) }}
name = zope hostalias-dict = {{ dumps(slapparameter_dict['hostalias-dict']) }}
log = ${zope-instance:event-log} ${zope-instance:z2-log}
frequency = daily
rotate-num = 30
post = {{ bin_directory }}/killpidfromfile ${zope-instance:pid-file} SIGUSR2
sharedscripts = true
notifempty = true
create = true
[logrotate-entry-apache-zope-backend] # Note: there is a subtle difference between hosts and hostaliases files:
<= logrotate # - hosts files start with resolved, followed by alias(es) (only one alias per
recipe = slapos.cookbook:logrotate.d # line in this case)
name = zope # - hostaliases start with alias, followed by resolved
log = ${apache-zope-backend-instance:error-log} ${apache-zope-backend-instance:access-log} # ...so it's not possible to merge these templates (not a big deal anyway).
frequency = daily
rotate-num = 30
post = {{ bin_directory }}/killpidfromfile ${apache-zope-backend-instance:pid-file} SIGUSR1
sharedscripts = true
notifempty = true
create = true
[cron] [hostaliases]
recipe = slapos.cookbook:cron recipe = slapos.recipe.template:jinja2
dcrond-binary = {{ dcron_location }}/sbin/crond template = inline: {{ '
cron-entries = ${directory:cron-entries} {% for alias, aliased in host_dict.items() -%}
crontabs = ${directory:crontabs} {{ alias }} {{ aliased }}
cronstamps = ${directory:cronstamps} {% endfor %}
catcher = ${cron-simplelogger:wrapper} ' }}
binary = ${basedirectory:services}/crond rendered = ${directory:etc}/hostaliases
context = key host_dict hosts-parameter:hostalias-dict
[cron-simplelogger] [hosts]
recipe = slapos.cookbook:simplelogger recipe = slapos.recipe.template:jinja2
wrapper = ${rootdirectory:bin}/cron_simplelogger template = inline: {{ '
log = ${basedirectory:log}/cron.log {% for alias, aliased in host_dict.items() -%}
{{ aliased }} {{ alias }}
{% endfor %}
' }}
rendered = ${directory:etc}/hosts
context = key host_dict hosts-parameter:host-dict
[cron-entry-logrotate] [preload-userhosts-runzope-parameter]
<= cron runzope-binary = {{ bin_directory }}/runzope
recipe = slapos.cookbook:cron.d userhosts = {{ parameter_dict['userhosts'] }}
name = logrotate shell-path = {{ parameter_dict['dash'] }}/bin/dash
frequency = 0 0 * * * hosts = ${hosts:rendered}
command = ${logrotate:wrapper} hostaliases = ${hostaliases:rendered}
[binary-link] [preload-userhosts-runzope]
recipe = slapos.cookbook:symbolic.link recipe = slapos.recipe.template:jinja2
target-directory = ${rootdirectory:bin} rendered = ${directory:bin}/runzope_userhosts_preloaded
link-binary = context = section parameter_dict preload-userhosts-runzope-parameter
{{ coreutils_location }}/bin/basename template = {{ parameter_dict['runzope-userhosts-preloaded-template'] }}
{{ coreutils_location }}/bin/cat mode = 755
{{ coreutils_location }}/bin/cp
{{ coreutils_location }}/bin/ls
{{ coreutils_location }}/bin/tr
{{ coreutils_location }}/bin/uname
{{ git_location }}/bin/git
{{ graphviz_location }}/bin/dot
{{ grep_location }}/bin/grep
{{ imagemagick_location }}/bin/convert
{{ imagemagick_location }}/bin/identify
{{ librsvg_location }}/bin/rsvg-convert
{{ mariadb_location }}/bin/mysql
{{ mariadb_location }}/bin/mysqldump
{{ sed_location }}/bin/sed
{{ tesseract_location }}/bin/tesseract
{{ w3m_location }}/bin/w3m
{{ openssl_location }}/bin/openssl
{{ poppler_location }}/bin/pdfinfo
{{ poppler_location }}/bin/pdfseparate
{{ poppler_location }}/bin/pdftotext
{{ poppler_location }}/bin/pdftohtml
{{ poppler_location }}/bin/pdfunite
{{ dmtx_utils_location }}/bin/dmtxwrite
{{ aspell_location }}/bin/aspell
{{ jsl_location }}/bin/jsl
[certificate-authority]
recipe = slapos.cookbook:certificate_authority
openssl-binary = {{ openssl_location }}/bin/openssl
ca-dir = ${directory:ca-dir}
requests-directory = ${cadirectory:requests}
wrapper = ${basedirectory:services}/ca
ca-private = ${cadirectory:private}
ca-certs = ${cadirectory:certs}
ca-newcerts = ${cadirectory:newcerts}
ca-crl = ${cadirectory:crl}
[bt5-erp5-link] [zope-base]
recipe = slapos.cookbook:symbolic.link recipe = slapos.cookbook:generic.zope.zeo.client
target-directory = ${basedirectory:bt5-erp5} inituser = ${directory:instance}/inituser
link-binary = user = {{ dumps(slapparameter_dict['inituser-login']) }}
{{ erp5_location }}/product/ERP5/bootstrap password = {{ dumps(slapparameter_dict['inituser-password']) }}
{{ erp5_location }}/bt5 timezone = {{ dumps(slapparameter_dict['timezone']) }}
tmp-path = ${directory:tmp}
bin-path = ${directory:bin}:{{ parameter_dict['coreutils'] }}/bin
site-zcml = ${directory:instance-etc}/site.zcml
runzope-binary = ${preload-userhosts-runzope:rendered}
bt5-repository =
[cadirectory] [zope-conf-parameter-base]
recipe = slapos.cookbook:mkdirectory ip = {{ ipv4 }}
requests = ${directory:ca-dir}/requests site-id = {{ site_id }}
private = ${directory:ca-dir}/private {% set storage_dict = {'neo': {}, 'zeo': slapparameter_dict.get('zodb-zeo', {})} -%}
certs = ${directory:ca-dir}/certs {% for name, zodb in zodb_dict.iteritems() -%}
newcerts = ${directory:ca-dir}/newcerts {% do zodb.setdefault('storage-dict', {}).update(storage_dict[zodb['type']].get(name, {})) -%}
crl = ${directory:ca-dir}/crl {% endfor -%}
developer-list = {{ dumps(slapparameter_dict['developer-list']) }}
instance = ${directory:instance}
instance-products = ${directory:instance-products}
deadlock-path = /manage_debug_threads
deadlock-debugger-password = {{ dumps(slapparameter_dict['deadlock-debugger-password']) }}
{% if slapparameter_dict.get('tidstorage-ip') -%}
tidstorage-ip = {{ dumps(slapparameter_dict['tidstorage-ip']) }}
tidstorage-port = {{ dumps(slapparameter_dict['tidstorage-port']) }}
{% endif -%}
promise-path = ${erp5-promise:promise-path}
{% set thread_amount = slapparameter_dict['thread-amount'] -%}
thread-amount = {{ thread_amount }}
{% set webdav = slapparameter_dict['webdav'] -%}
webdav = {{ dumps(webdav) }}
{% if webdav -%}
{% set timerserver_interval = 0 -%}
{% else -%}
{% set timerserver_interval = slapparameter_dict['timerserver-interval'] -%}
{%- endif %}
timerserver-interval = {{ dumps(timerserver_interval) }}
[rootdirectory] [zope-conf-base]
recipe = slapos.cookbook:mkdirectory recipe = slapos.recipe.template:jinja2
etc = ${buildout:directory}/etc template = {{ parameter_dict['zope-conf-template'] }}
var = ${buildout:directory}/var
srv = ${buildout:directory}/srv
bin = ${buildout:directory}/bin
tmp = ${buildout:directory}/tmp
[basedirectory] [logrotate-entry-base]
recipe = slapos.cookbook:mkdirectory recipe = slapos.cookbook:logrotate.d
log = ${rootdirectory:var}/log logrotate-entries = ${logrotate:logrotate-entries}
services = ${rootdirectory:etc}/run backup = ${logrotate:backup}
promises = ${rootdirectory:etc}/promise/
run = ${rootdirectory:var}/run
backup = ${rootdirectory:srv}/backup
bt5-erp5 = ${rootdirectory:var}/bt5_erp5
[erp5-certificate-authority] {% macro zope(
recipe = slapos.cookbook:certificate_authority index,
openssl-binary = {{ openssl_location }}/bin/openssl port,
ca-dir = ${directory:erp5-ca-dir} longrequest_logger_timeout,
requests-directory = ${erp5-cadirectory:requests} longrequest_logger_interval
wrapper = ${basedirectory:services}/erp5-ca ) -%}
ca-private = ${erp5-cadirectory:private} {% set name = 'zope-' ~ index -%}
ca-certs = ${erp5-cadirectory:certs} {% set conf_name = name ~ '-conf' -%}
ca-newcerts = ${erp5-cadirectory:newcerts} {% set conf_parameter_name = conf_name ~ '-param' -%}
ca-crl = ${erp5-cadirectory:crl} {% set zope_tunnel_section_name = name ~ '-ipv6toipv4' -%}
{% set zope_tunnel_base_name = zope_tunnel_section_name -%}
[{{ conf_parameter_name }}]
< = zope-conf-parameter-base
pid-file = ${directory:run}/{{ name }}.pid
lock-file = ${directory:run}/{{ name }}.lock
port = {{ port }}
event-log = ${directory:log}/{{ name }}-event.log
z2-log = ${directory:log}/{{ name }}-Z2.log
node-id = {{ dumps(node_id_base ~ '-' ~ index) }}
{% set log_list = [] -%}
{% set import_set = set() -%}
{% for db_name, zodb in zodb_dict.iteritems() -%}
{% if zodb['type'] == 'neo' -%}
{% do import_set.add('neo.client') -%}
{% set log = buildout_directory ~ '/var/log/' ~ name ~ '-neo-' ~ db_name ~ '.log' -%}
{% do log_list.append(log) -%}
{% do zodb['storage-dict'].__setitem__('logfile', log) -%}
{% if db_name == slapparameter_dict.get('neo-name') -%}
{% do zodb['storage-dict'].__setitem__('name', slapparameter_dict['neo-cluster']) -%}
{% do zodb['storage-dict'].__setitem__('master_nodes', slapparameter_dict['neo-masters']) -%}
{% endif -%}
{{ assert(zodb['storage-dict']['master_nodes'], db_name) }}
{% endif -%}
{% endfor -%}
import-list = {{ dumps(list(import_set)) }}
zodb-dict = {{ dumps(zodb_dict) }}
[erp5-cadirectory] [{{ conf_name }}]
recipe = slapos.cookbook:mkdirectory < = zope-conf-base
requests = ${directory:erp5-ca-dir}/requests rendered = ${directory:etc}/{{ name }}.conf
private = ${directory:erp5-ca-dir}/private context =
certs = ${directory:erp5-ca-dir}/certs section parameter_dict {{ conf_parameter_name }}
newcerts = ${directory:erp5-ca-dir}/newcerts
crl = ${directory:erp5-ca-dir}/crl
[directory] [{{ section(name) }}]
recipe = slapos.cookbook:mkdirectory < = zope-base
zodb = ${rootdirectory:srv}/zodb {% if longrequest_logger_interval < 0 -%}
instance = ${rootdirectory:srv}/erp5shared longrequest-logger-file =
instance-etc = ${:instance}/etc longrequest-logger-timeout =
apache-conf = ${rootdirectory:etc}/apache longrequest-logger-interval =
instance-etc-package-include = ${:instance}/etc/package-include {% else -%}
# because of bug in slapos.recipe.template keys are lowercased longrequest-logger-file = {{ longrequest_logger_base_path ~ name ~ ".log" }}
instance-document = ${:instance}/Document longrequest-logger-timeout = {{ longrequest_logger_timeout }}
instance-propertysheet = ${:instance}/PropertySheet longrequest-logger-interval = {{ longrequest_logger_interval }}
instance-products = ${:instance}/Products {% endif -%}
instance-extensions = ${:instance}/Extensions wrapper = ${directory:services}/{{ name }}
instance-constraint = ${:instance}/Constraint configuration-file = {{ '${' ~ conf_name ~ ':rendered}' }}
instance-import = ${:instance}/import
instance-lib = ${:instance}/lib
instance-tests = ${:instance}/tests
erp5-ca-dir = ${rootdirectory:srv}/erp5-ca
ca-dir = ${rootdirectory:srv}/ssl
cron-entries = ${rootdirectory:etc}/cron.d
crontabs = ${rootdirectory:etc}/crontabs
cronstamps = ${rootdirectory:etc}/cronstamps
logrotate-backup = ${basedirectory:backup}/logrotate
logrotate-entries = ${rootdirectory:etc}/logrotate.d
# Deploy zope promises scripts [{{ section("promise-" ~ name) }}]
[promise-zope]
recipe = slapos.cookbook:check_port_listening recipe = slapos.cookbook:check_port_listening
path = ${basedirectory:promises}/zope hostname = {{ ipv4 }}
hostname = ${zope-instance:ip} port = {{ port }}
port = ${zope-instance:port} path = ${directory:promises}/{{ name }}
[promise-apache-zope-backend] {% if use_ipv6 -%}
[{{ zope_tunnel_section_name }}]
< = ipv6toipv4-base
base-name = {{ zope_tunnel_base_name }}
ipv6-port = {{ port }}
ipv4-port = {{ port }}
{% do publish_list.append(("[" ~ ipv6 ~ "]:" ~ port, thread_amount, webdav)) -%}
[{{ section("promise-tunnel-" ~ name) }}]
recipe = slapos.cookbook:check_port_listening recipe = slapos.cookbook:check_port_listening
path = ${basedirectory:promises}/apache-backend hostname = {{ '${' ~ zope_tunnel_section_name ~ ':ipv6}' }}
hostname = ${apache-zope-backend-instance:ip} port = {{ '${' ~ zope_tunnel_section_name ~ ':ipv6-port}' }}
port = ${apache-zope-backend-instance:port} path = ${directory:promises}/{{ zope_tunnel_base_name }}
{% else -%}
{% do publish_list.append((ipv4 ~ ":" ~ port, thread_amount, webdav)) -%}
{% endif -%}
[{{ section('logrotate-entry-' ~ name) }}]
< = logrotate-entry-base
name = {{ name }}
log = {{ '${' ~ conf_parameter_name ~ ':event-log}' }} {{ '${' ~ conf_parameter_name ~ ':z2-log}' }} {{ '${' ~ name ~ ':longrequest-logger-file}' }} {{ ' '.join(log_list) }}
post = {{ bin_directory }}/slapos-kill --pidfile {{ '${' ~ conf_parameter_name ~ ':pid-file}' }} -s USR2
{% endmacro -%}
{% for i in range(slapparameter_dict['instance-count']) -%}
{{ zope(
i,
next_port,
slapparameter_dict['longrequest-logger-timeout'],
slapparameter_dict['longrequest-logger-interval'],
) }}
{% set next_port = next_port + 1 -%}
{% endfor -%}
[publish-zope]
recipe = slapos.cookbook:publish.serialised
zope-address-list = {{ dumps(publish_list) }}
{#
Note: hosts_dist is generated at zope level rather than at erp5 (root partition)
level, as it is easier: we can access urls as python values trivially here.
This has the downside of making each zope partition publish the (hopefuly) same
dict toward erp5 partition, violating the DRY principle and making the intent
hard to guess.
-#}
hosts-dict = {{ dumps(hosts_dict) }}
[erp5-promise]
recipe = slapos.cookbook:erp5.promise
promise-path = ${directory:etc}/erp5promise.cfg
kumofs-url = {{ dumps(slapparameter_dict['kumofs-url']) }}
memcached-url = {{ dumps(slapparameter_dict['memcached-url']) }}
cloudooo-url = {{ dumps(slapparameter_dict['cloudooo-url']) }}
smtp-url = {{ dumps(slapparameter_dict['smtp-url']) }}
bt5 = {{ dumps(slapparameter_dict['bt5']) }}
bt5-repository-url = {{ dumps(slapparameter_dict['bt5-repository-url']) }}
[buildout]
extends = {{ logrotate_cfg }}
parts +=
erp5-promise
{{ part_list | join('\n ') }}
publish-zope
versions = versions
[versions] [versions]
slapos.core = {{ slapos_core_version }} slapos.core = {{ slapos_core_version }}
[buildout] [buildout]
parts = extends = {{ instance_common_cfg }}
switch-softwaretype
eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
[slap-parameters]
recipe = slapos.cookbook:slapconfiguration
computer = ${slap-connection:computer-id}
partition = ${slap-connection:partition-id}
url = ${slap-connection:server-url}
key = ${slap-connection:key-file}
cert = ${slap-connection:cert-file}
[jinja2-template-base] [jinja2-template-base]
recipe = slapos.recipe.template:jinja2 context +=
rendered = ${buildout:parts-directory}/${:_buildout_section_name_}/${:filename}
extra-context =
context =
key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory
key slap_software_type slap-parameters:slap-software-type
key slapparameter_dict slap-parameters:configuration
raw slapos_core_version {{ slapos_core_version }} raw slapos_core_version {{ slapos_core_version }}
${:extra-context}
[dynamic-template-tidstorage-parameters]
apache = {{ apache_location }}
haproxy = {{ haproxy_location }}
dcron = {{ dcron_location }}
logrotate = {{ logrotate_location }}
gzip = {{ gzip_location }}
openssl = {{ openssl_location }}
coreutils = {{ coreutils_location }}
git = {{ git_location }}
graphviz = {{ graphviz_location }}
grep = {{ grep_location }}
imagemagick = {{ imagemagick_location }}
librsvg = {{ librsvg_location }}
mariadb = {{ mariadb_location }}
sed = {{ sed_location }}
tesseract = {{ tesseract_location }}
w3m = {{ w3m_location }}
aspell = {{ aspell_location }}
poppler = {{ poppler_location }}
dmtx-utils = {{ dmtx_utils_location }}
buildout-bin-directory = {{ buildout_bin_directory }}
zope-conf-template = {{ template_zope_conf }}
jsl = {{ jsl_location }}
[dynamic-template-tidstorage]
< = jinja2-template-base
template = {{ template_tidstorage }}
filename = instance-tidstorage.cfg
extensions = jinja2.ext.do
extra-context =
section parameter_dict dynamic-template-tidstorage-parameters
import json_module json
raw zope_port_base 12000
raw zeo_port_base 15000
raw haproxy_port_base 11000
raw apache_port_base 10000
key ipv4_set slap-parameters:ipv4
key ipv6_set slap-parameters:ipv6
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type tidstorage
[dynamic-template-cloudooo-parameters] [dynamic-template-cloudooo-parameters]
cups = {{ cups_location }} cups = {{ cups_location }}
...@@ -94,179 +32,139 @@ zlib = {{ zlib_location }} ...@@ -94,179 +32,139 @@ zlib = {{ zlib_location }}
libreoffice-bin = {{ libreoffice_bin_location }} libreoffice-bin = {{ libreoffice_bin_location }}
fonts = {{ fonts_location }} fonts = {{ fonts_location }}
buildout-bin-directory = {{ buildout_bin_directory }} buildout-bin-directory = {{ buildout_bin_directory }}
6tunnel = {{ sixtunnel_location }}
dash = {{ dash_location }}
[dynamic-template-cloudooo] [dynamic-template-cloudooo]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_cloudooo }} template = {{ template_cloudooo }}
filename = instance-cloudoo.cfg filename = instance-cloudoo.cfg
extra-context = extra-context =
section parameter_dict dynamic-template-cloudooo-parameters section parameter_dict dynamic-template-cloudooo-parameters
import json_module json
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type cloudooo
[dynamic-template-varnish-parameters] [dynamic-template-erp5-parameters]
local-bt5-repository = {{ local_bt5_repository }}
[dynamic-template-erp5]
<= jinja2-template-base
template = {{ template_erp5 }}
filename = instance-erp5.cfg
extra-context =
key local_bt5_repository dynamic-template-erp5-parameters:local-bt5-repository
import urlparse urlparse
import-list =
rawfile root_common {{ root_common }}
[dynamic-template-balancer-parameters]
apache = {{ apache_location }}
openssl = {{ openssl_location }}
haproxy = {{ haproxy_location }}
bin-directory = {{ bin_directory }}
6tunnel = {{ sixtunnel_location }}
dash = {{ dash_location }} dash = {{ dash_location }}
dcron = {{ dcron_location }} template-haproxy-cfg = {{ template_haproxy_cfg }}
gzip = {{ gzip_location }} template-apache-conf = {{ template_apache_conf }}
logrotate = {{ logrotate_location }}
stunnel = {{ stunnel_location }}
varnish = {{ varnish_location }}
wget = {{ wget_location }}
buildout-bin-directory = {{ buildout_bin_directory }}
[dynamic-template-varnish] [dynamic-template-balancer]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_varnish }} template = {{ template_balancer }}
filename = instance-varnish.cfg filename = instance-balancer.cfg
extra-context = extra-context =
section parameter_dict dynamic-template-varnish-parameters section parameter_dict dynamic-template-balancer-parameters
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type varnish
[dynamic-template-mariadb-parameters] [dynamic-template-zeo-parameters]
buildout-bin-directory = {{ buildout_bin_directory }} buildout-bin-directory = {{ buildout_bin_directory }}
[dynamic-template-mariadb] [dynamic-template-zeo]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_mariadb }} template = {{ template_zeo }}
filename = instance-mariadb.cfg filename = instance-zeo.cfg
extra-context = extra-context =
section parameter_dict dynamic-template-mariadb-parameters key buildout_directory buildout:directory
raw coreutils_location {{ coreutils_location }} section parameter_dict dynamic-template-zeo-parameters
raw dash_location {{ dash_location }}
raw dcron_location {{ dcron_location }}
raw findutils_location {{ findutils_location }}
raw gettext_location {{ gettext_location }}
raw grep_location {{ grep_location }}
raw gzip_location {{ gzip_location }}
raw logrotate_location {{ logrotate_location }}
raw mariadb_location {{ mariadb_location }}
raw mariadb_resiliency_after_import_script {{ mariadb_resiliency_after_import_script }}
raw perl_location {{ perl_location }}
raw perl_siteprefix {{ perl_siteprefix }}
raw sed_location {{ sed_location }}
raw xtrabackup_location {{ xtrabackup_location }}
import json_module json import json_module json
# Must match the key id in [switch-softwaretype] which uses this section.
raw software_type mariadb
[dynamic-template-zope-parameters] [dynamic-template-zope-parameters]
apache = {{ apache_location }}
aspell = {{ aspell_location }}
bin-directory = {{ bin_directory }} bin-directory = {{ bin_directory }}
zope-conf-template = {{ template_zope_conf }}
buildout-bin-directory = {{ buildout_bin_directory }}
6tunnel = {{ sixtunnel_location }}
coreutils = {{ coreutils_location }} coreutils = {{ coreutils_location }}
dcron = {{ dcron_location }} dash = {{ dash_location }}
dmtx-utils = {{ dmtx_utils_location }}
erp5 = {{ erp5_location }}
git = {{ git_location }}
graphviz = {{ graphviz_location }}
grep = {{ grep_location }}
gzip = {{ gzip_location }}
imagemagick = {{ imagemagick_location }}
librsvg = {{ librsvg_location }}
logrotate = {{ logrotate_location }}
mariadb = {{ mariadb_location }}
openssl = {{ openssl_location }}
poppler = {{ poppler_location }}
sed = {{ sed_location }}
tesseract = {{ tesseract_location }}
w3m = {{ w3m_location }}
jsl = {{ jsl_location }} jsl = {{ jsl_location }}
link-binary = {{ dumps(zope_link_binary) }}
userhosts = {{ userhosts_location }}
runzope-userhosts-preloaded-template = {{ template_runzope_userhosts_preloaded }}
[dynamic-template-zope] [dynamic-template-zope]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_zope }} template = {{ template_zope }}
filename = instance-zope.cfg filename = instance-zope.cfg
extensions = jinja2.ext.do
# XXX: duplicates above section, so less is modified in template in this
# commit. Should be replaced by a single "section" line.
extra-context = extra-context =
key apache_location dynamic-template-zope-parameters:apache key buildout_directory buildout:directory
key aspell_location dynamic-template-zope-parameters:aspell section parameter_dict dynamic-template-zope-parameters
key bin_directory dynamic-template-zope-parameters:bin-directory import urlparse urlparse
key coreutils_location dynamic-template-zope-parameters:coreutils
key dcron_location dynamic-template-zope-parameters:dcron [dynamic-template-kumofs-parameters]
key dmtx_utils_location dynamic-template-zope-parameters:dmtx-utils dash-location = {{ dash_location }}
key erp5_location dynamic-template-zope-parameters:erp5 dcron-location = {{ dcron_location }}
key git_location dynamic-template-zope-parameters:git gzip-location = {{ gzip_location }}
key graphviz_location dynamic-template-zope-parameters:graphviz kumo-location = {{ kumo_location }}
key grep_location dynamic-template-zope-parameters:grep logrotate-location = {{ logrotate_location }}
key gzip_location dynamic-template-zope-parameters:gzip
key imagemagick_location dynamic-template-zope-parameters:imagemagick [dynamic-template-kumofs]
key librsvg_location dynamic-template-zope-parameters:librsvg <= jinja2-template-base
key logrotate_location dynamic-template-zope-parameters:logrotate template = {{ template_kumofs }}
key mariadb_location dynamic-template-zope-parameters:mariadb filename = instance-kumofs.cfg
key openssl_location dynamic-template-zope-parameters:openssl extra-context =
key poppler_location dynamic-template-zope-parameters:poppler section parameter_dict dynamic-template-kumofs-parameters
key sed_location dynamic-template-zope-parameters:sed
key tesseract_location dynamic-template-zope-parameters:tesseract
key w3m_location dynamic-template-zope-parameters:w3m
key jsl_location dynamic-template-zope-parameters:jsl
[template-erp5-single-parameters] [dynamic-template-mariadb-parameters]
coreutils-location = {{ coreutils_location }}
dash-location = {{ dash_location }}
findutils-location = {{ findutils_location }}
gzip-location = {{ gzip_location }}
mariadb-location = {{ mariadb_location }}
template-my-cnf = {{ template_my_cnf }}
template-mariadb-initial-setup = {{ template_mariadb_initial_setup }}
link-binary = {{ dumps(mariadb_link_binary) }}
bin-directory = {{ bin_directory }} bin-directory = {{ bin_directory }}
openssl = {{ openssl_location }} mariadb-resiliency-after-import-script = {{ mariadb_resiliency_after_import_script }}
local_bt5_repository = {{ local_bt5_repository }}
bt5_list = {{ bt5_list }}
dash = {{ dash_location }}
curl = {{ curl_location }}
[template-erp5-single] [dynamic-template-mariadb]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_erp5_single }} template = {{ template_mariadb }}
filename = instance-erp5-single.cfg filename = instance-mariadb.cfg
# XXX: duplicates above section, so less is modified in template in this
# commit. Should be replaced by a "section" line (preserving template_zope
# definition).
extra-context = extra-context =
key bin_directory template-erp5-single-parameters:bin-directory section parameter_dict dynamic-template-mariadb-parameters
key openssl_location template-erp5-single-parameters:openssl
key curl_location template-erp5-single-parameters:curl
key dash_location template-erp5-single-parameters:dash
key template_zope dynamic-template-zope:rendered
key local_bt5_repository template-erp5-single-parameters:local_bt5_repository
key bt5_list template-erp5-single-parameters:bt5_list
[dynamic-template-cluster-parameters] [dynamic-template-create-erp5-site-parameters]
local-bt5-repository = {{ local_bt5_repository }} instance-erp5 = ${dynamic-template-erp5:rendered}
bt5_list = {{ bt5_list }} template-create-erp5-site-real = {{ template_create_erp5_site_real }}
dash-location = {{ dash_location }}
curl-location = {{ curl_location }}
[dynamic-template-cluster] [dynamic-template-create-erp5-site]
< = jinja2-template-base <= jinja2-template-base
template = {{ template_erp5_cluster }} template = {{ template_create_erp5_site }}
filename = instance-erp5-cluster.cfg filename = instance-create-erp5-site.cfg
extra-context = extra-context =
key local_bt5_repository dynamic-template-cluster-parameters:local-bt5-repository section parameter_dict dynamic-template-create-erp5-site-parameters
key bt5_list template-erp5-single-parameters:bt5_list
# Must match the key id in [switch-softwaretype] which uses this section.
# XXX: it is dangerous to use buildout-style expansion in jinja context declaration
raw software_type ${:software-type}
software-type = cluster
# BBB: use "cluster" software type instead
[dynamic-template-production]
< = dynamic-template-cluster
software-type = production
[switch-softwaretype] [switch-softwaretype]
recipe = slapos.cookbook:softwaretype recipe = slapos.cookbook:switch-softwaretype
default = ${template-erp5-single:rendered} override = {{ dumps(override_switch_softwaretype |default) }}
production = ${dynamic-template-production:rendered}
cluster = ${dynamic-template-cluster:rendered} # Public software types
kumofs = {{ template_kumofs }} default = dynamic-template-erp5:rendered
memcached = {{ template_memcached }} create-erp5-site = dynamic-template-create-erp5-site:rendered
cloudooo = ${dynamic-template-cloudooo:rendered} # BBB
zope = ${dynamic-template-zope:rendered} RootSoftwareInstance = ${:default}
mariadb = ${dynamic-template-mariadb:rendered} # Internal software types
tidstorage = ${dynamic-template-tidstorage:rendered} kumofs = dynamic-template-kumofs:rendered
varnish = ${dynamic-template-varnish:rendered} cloudooo = dynamic-template-cloudooo:rendered
mariadb = dynamic-template-mariadb:rendered
[slap-connection] balancer = dynamic-template-balancer:rendered
# part to migrate to new - separated words zodb-zeo = dynamic-template-zeo:rendered
computer-id = ${slap_connection:computer_id} zodb-neo = neo-storage-mysql:rendered
partition-id = ${slap_connection:partition_id} zope = dynamic-template-zope:rendered
server-url = ${slap_connection:server_url}
software-release-url = ${slap_connection:software_release_url}
key-file = ${slap_connection:key_file}
cert-file = ${slap_connection:cert_file}
USE mysql;
DROP FUNCTION IF EXISTS last_insert_grn_id;
{% set mroonga = parameter_dict.get('mroonga', 'ha_mroonga.so') -%}
{% if mroonga %}CREATE FUNCTION last_insert_grn_id RETURNS INTEGER SONAME '{{ mroonga }}';{% endif %}
DROP FUNCTION IF EXISTS sphinx_snippets;
#CREATE FUNCTION sphinx_snippets RETURNS STRING SONAME 'ha_sphinx.so';
{% macro database(name, user, password) -%}
CREATE DATABASE IF NOT EXISTS {{ name }};
{% if user -%}
GRANT ALL PRIVILEGES ON {{ name }}.* TO {{ user }}@'%' IDENTIFIED BY '{{ password }}';
GRANT ALL PRIVILEGES ON {{ name }}.* TO {{ user }}@'localhost' IDENTIFIED BY '{{ password }}';
{%- endif %}
{% endmacro -%}
{% for entry in parameter_dict['database-list'] -%}
{{ database(entry['name'], entry.get('user'), entry.get('password')) }}
{% endfor -%}
{% set socket = parameter_dict['socket'] -%}
# ERP5 buildout my.cnf template based on my-huge.cnf shipped with mysql
# The MySQL server
[mysqld]
# ERP5 by default requires InnoDB storage. MySQL by default fallbacks to using
# different engine, like MyISAM. Such behaviour generates problems only, when
# tables requested as InnoDB are silently created with MyISAM engine.
#
# Loud fail is really required in such case.
sql_mode="NO_ENGINE_SUBSTITUTION"
# Workaround for https://bugs.launchpad.net/maria/+bug/985828
# that causes wrong result in Resource_zGetInventoryList etc.
optimizer_switch = derived_merge=off
skip_show_database
{% set ip = parameter_dict.get('ip') -%}
{% if ip -%}
bind_address = {{ ip }}
port = {{ parameter_dict['port'] }}
{% else -%}
skip_networking
{% endif -%}
socket = {{ socket }}
datadir = {{ parameter_dict['data-directory'] }}
pid_file = {{ parameter_dict['pid-file'] }}
log_error = {{ parameter_dict['error-log'] }}
slow_query_log
slow_query_log_file = {{ parameter_dict['slow-query-log'] }}
long_query_time = {{ parameter_dict['long-query-time'] }}
max_allowed_packet = 128M
query_cache_size = 32M
innodb_file_per_table = 0
plugin_load = ha_mroonga.so;handlersocket.so
# By default only 100 connections are allowed, when using zeo
# we may have much more connections
max_connections = 1000
{% set innodb_buffer_pool_size = parameter_dict['innodb-buffer-pool-size'] -%}
{% if innodb_buffer_pool_size %}innodb_buffer_pool_size = {{ innodb_buffer_pool_size }}{% endif %}
{% set innodb_log_file_size = parameter_dict['innodb-log-file-size'] -%}
{% if innodb_log_file_size %} innodb_log_file_size = {{ innodb_log_file_size }}{% endif %}
{% set innodb_log_buffer_size = parameter_dict['innodb-log-buffer-size'] -%}
{% if innodb_log_buffer_size %} innodb_log_buffer_size = {{ innodb_log_buffer_size }}{% endif %}
# very important to allow parallel indexing
# Note: this is compatible with binlog-based incremental backups, because ERP5
# doesn't use "insert ... select" (in any number of queries) pattern.
innodb_locks_unsafe_for_binlog = 1
{% set log_bin = parameter_dict['binlog-path'] -%}
{% if log_bin -%}
log_bin = {{ log_bin }}
{% set binlog_expire_days = parameter_dict['binlog-expire-days'] -%}
{% if binlog_expire_days > 0 %}expire_logs_days = {{ binlog_expire_days }}{% endif %}
{% endif %}
# Some dangerous settings you may want to uncomment temporarily
# if you only want performance or less disk access.
{% set x = '' if parameter_dict['relaxed-writes'] else '#' -%}
{{x}}innodb_flush_log_at_trx_commit = 0
{{x}}innodb_flush_method = nosync
{{x}}innodb_doublewrite = 0
{{x}}sync_frm = 0
# Force utf8 usage
collation_server = utf8_unicode_ci
character_set_server = utf8
skip_character_set_client_handshake
{% if 'ssl-key' in parameter_dict -%}
ssl_cert = {{ parameter_dict['ssl-crt'] }}
ssl_key = {{ parameter_dict['ssl-key'] }}
{% if 'ssl-ca-crt' in parameter_dict -%}
ssl_ca = {{ parameter_dict['ssl-ca-crt'] }}
{%- endif %}
{% if 'ssl-crl' in parameter_dict -%}
ssl_crl = {{ parameter_dict['ssl-crl'] }}
{%- endif %}
{% if 'ssl-cipher' in parameter_dict -%}
ssl_cipher = {{ parameter_dict['ssl-cipher'] }}
{%- endif %}
{%- endif %}
[client]
socket = {{ socket }}
user = root
[mysql]
no_auto_rehash
[mysqlhotcopy]
interactive_timeout
#!{{ parameter_dict['shell-path'] }}
HOSTALIASES='{{ parameter_dict['hostaliases'] }}' HOSTS='{{ parameter_dict['hosts'] }}' exec '{{ parameter_dict['userhosts'] }}' '{{ parameter_dict['runzope-binary'] }}' "$@"
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
set -e set -e
mysql_executable="${mariadb-instance:mysql-binary}" mysql_executable="${binary-wrap-mysql:wrapper-path}"
mysqldump_executable="${binary-wrap-mysqldump:wrapper-path}" mysqldump_executable="${binary-wrap-mysqldump:wrapper-path}"
mariadb_data_directory="${directory:mariadb-data}" mariadb_data_directory="${directory:mariadb-data}"
mariadb_backup_directory="${directory:mariadb-backup-full}" mariadb_backup_directory="${directory:mariadb-backup-full}"
instance_directory="${buildout:directory}" instance_directory="${buildout:directory}"
pid_file="${mariadb-instance:pid-file}" pid_file="${my-cnf-parameters:pid-file}"
binlog_path="${mariadb-instance:binlog-path}" binlog_path="${my-cnf-parameters:binlog-path}"
# Make sure mariadb is not already running # Make sure mariadb is not already running
if [ -e "$pid_file" ]; then if [ -e "$pid_file" ]; then
......
# Note: Environment is setup in running wrapper script, as zope.conf is read # Note: Environment is setup in running wrapper script, as zope.conf is read
# too late for some components. # too late for some components.
%define INSTANCE {{ instance }} %define INSTANCE {{ parameter_dict['instance'] }}
instancehome $INSTANCE instancehome $INSTANCE
zserver-threads {{ parameter_dict['thread-amount'] }} zserver-threads {{ parameter_dict['thread-amount'] }}
# When ownership checking is enabled, the roles a script runs as are the
# intersection between user's roles and script owner's roles. This means
# that revoking a code author's access to the system prevent all scripts
# owned by that user from being of much use.
# This is not how ERP5 approaches development: Managers write code,
# Managers must be trustable and trusted, and their past work should not be
# revoked when their account is terminated.
skip-ownership-checking true
lock-filename {{ parameter_dict['lock-file'] }} lock-filename {{ parameter_dict['lock-file'] }}
pid-filename {{ parameter_dict['pid-file'] }} pid-filename {{ parameter_dict['pid-file'] }}
...@@ -12,38 +20,40 @@ rest-input-encoding utf-8 ...@@ -12,38 +20,40 @@ rest-input-encoding utf-8
rest-output-encoding utf-8 rest-output-encoding utf-8
# XXX: isn't this entry implicit ? # XXX: isn't this entry implicit ?
products {{ instance_products }} products {{ parameter_dict['instance-products'] }}
<http-server> {% if parameter_dict['webdav'] -%}
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
</http-server>
{# TODO: enable
{% if webdav_port -%}
<webdav-source-server> <webdav-source-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['webdav_port'] }} address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
force-connection-close off force-connection-close off
</webdav-source-server> </webdav-source-server>
{% else %}
<http-server>
address {{ parameter_dict['ip'] }}:{{ parameter_dict['port'] }}
</http-server>
{%- endif %}
{% endif -%}
-#}
<zoperunner> <zoperunner>
program $INSTANCE/bin/runzope program $INSTANCE/bin/runzope
</zoperunner> </zoperunner>
<product-config DeadlockDebugger> <product-config DeadlockDebugger>
dump_url /manage_debug_threads dump_url {{ parameter_dict['deadlock-path'] }}
secret {{ deadlock_debugger_password }} secret {{ parameter_dict['deadlock-debugger-password'] }}
</product-config> </product-config>
{% if tidstorage_ip -%} {% if 'tidstorage-ip' in parameter_dict -%}
<product-config TIDStorage> <product-config TIDStorage>
backend-ip {{ tidstorage_ip }} backend-ip {{ parameter_dict['tidstorage-ip'] }}
backend-port {{ tidstorage_port }} backend-port {{ parameter_dict['tidstorage-port'] }}
</product-config> </product-config>
{% endif -%} {% endif -%}
{% set timerserver_interval = parameter_dict.get('timerserver-interval', '0') | int -%} <product-config CMFActivity>
node-id {{ parameter_dict['node-id'] }}
</product-config>
{% set timerserver_interval = parameter_dict['timerserver-interval'] -%}
{% if timerserver_interval -%} {% if timerserver_interval -%}
%import timerserver %import timerserver
<timer-server> <timer-server>
...@@ -51,6 +61,7 @@ products {{ instance_products }} ...@@ -51,6 +61,7 @@ products {{ instance_products }}
</timer-server> </timer-server>
{% endif -%} {% endif -%}
{% set promise_path = parameter_dict['promise-path'] -%}
{% if promise_path -%} {% if promise_path -%}
<product-config /{{ parameter_dict['site-id'] }}> <product-config /{{ parameter_dict['site-id'] }}>
promise_path {{ promise_path }} promise_path {{ promise_path }}
...@@ -81,12 +92,25 @@ products {{ instance_products }} ...@@ -81,12 +92,25 @@ products {{ instance_products }}
container-class Products.TemporaryFolder.TemporaryContainer container-class Products.TemporaryFolder.TemporaryContainer
</zodb_db> </zodb_db>
{% for db_name, mount_point, cache_size, storage_type, storage_dict in parameter_dict['zodb-list'] -%} {% set developer_list = parameter_dict['developer-list'] -%}
<zodb_db {{ db_name }}> {% if developer_list -%}
{%- if cache_size %} %import Products.ERP5Type
cache-size {{ cache_size }} <ERP5Type erp5>
{%- endif %} developers {{ developer_list | join(' ') }}
mount-point {{ mount_point }} </ERP5Type>
{% endif -%}
{% for m in parameter_dict['import-list'] -%}
%import {{ m }}
{% endfor -%}
{% set type_dict = {'neo': 'NEOStorage', 'zeo': 'zeoclient'} %}
{% for name, zodb_dict in parameter_dict['zodb-dict'].iteritems() %}
<zodb_db {{ name }}>
{%- set storage_type = type_dict[zodb_dict.pop('type')] %}
{%- set storage_dict = zodb_dict.pop('storage-dict') %}
{%- for key, value in zodb_dict.iteritems() %}
{{ key }} {{ value }}
{%- endfor %}
<{{ storage_type }}> <{{ storage_type }}>
{%- for key, value in storage_dict.iteritems() %} {%- for key, value in storage_dict.iteritems() %}
{{ key }} {{ value }} {{ key }} {{ value }}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment