Merge branch 'erp5' into erp5-generic
[slapos.git] / slapos / recipe / generate_erp5_tidstorage.py
1 ##############################################################################
2 #
3 # Copyright (c) 2011 Vifib SARL and Contributors. All Rights Reserved.
4 #
5 # WARNING: This program as such is intended to be used by professional
6 # programmers who take the whole responsibility of assessing all potential
7 # consequences resulting from its eventual inadequacies and bugs
8 # End users who are looking for a ready-to-use solution with commercial
9 # guarantees and support are strongly adviced to contract a Free Software
10 # Service Company
11 #
12 # This program is Free Software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; either version 3
15 # of the License, or (at your option) any later version.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #
26 ##############################################################################
27 from slapos.recipe.librecipe import GenericSlapRecipe
28 import os
29 import json
30 import traceback
31
32 SECTION_BACKEND_PUBLISHER = """[publish-apache-backend-list]
33 recipe = slapos.cookbook:publish"""
34 ZOPE_PORT_BASE = 12000
35 ZEO_PORT_BASE = 15000
36 HAPROXY_PORT_BASE = 11000
37 APACHE_PORT_BASE = 10000
38
39 class Recipe(GenericSlapRecipe):
40 def _options(self, options):
41 self.dirname = os.path.join(self.buildout['buildout']['parts-directory'],
42 self.name)
43 options['output'] = os.path.join(self.dirname, self.name + '.cfg')
44
45 def _generateRealTemplate(self):
46 current_zeo_port = ZEO_PORT_BASE
47 current_zope_port = ZOPE_PORT_BASE
48 current_apache_port = APACHE_PORT_BASE
49 current_haproxy_port = HAPROXY_PORT_BASE
50 json_data = json.loads(self.parameter_dict['json'])
51 site_id = str(json_data['site-id'])
52 # prepare zeo
53 output = ''
54 part_list = []
55 zope_dict = {}
56 zope_connection_dict = {}
57 known_tid_storage_identifier_dict = {}
58 snippet_zeo = open(self.options['snippet-zeo']).read()
59 for zeo_id, zeo_configuration_list in json_data['zeo'].iteritems():
60 storage_list = []
61 a = storage_list.append
62 for zeo_slave in zeo_configuration_list:
63 zope_connection_dict[zeo_slave['storage-name']] = {
64 'zope-cache-size': zeo_slave['zope-cache-size'],
65 'zeo-cache-size': zeo_slave['zeo-cache-size'],
66 'mount-point': zeo_slave['mount-point'] % {'site-id': site_id},
67 'storage-name': zeo_slave['storage-name'],
68 'server': '${zeo-instance-%(zeo-id)s:ip}:${zeo-instance-%(zeo-id)s:port}' % {'zeo-id': zeo_id}
69 }
70 zodb_path = os.path.join('${directory:zodb}', zeo_slave['storage-name'] + '.fs')
71 a(' storage-name=%(storage-name)s zodb-path=%(zodb-path)s' % {'zodb-path': zodb_path, 'storage-name': zeo_slave['storage-name']})
72 known_tid_storage_identifier_dict[
73 "((('%(ip)s', %(port)s),), '%(storage_name)s')" % dict(
74 ip='${zeo-instance-%s:ip}' % zeo_id,
75 port='${zeo-instance-%s:port}' % zeo_id,
76 storage_name=zeo_slave['storage-name'])] = (zodb_path, '${directory:zodb-backup}/%s/' % zeo_slave['storage-name'], zeo_slave['serialize-path'] % {'site-id': site_id})
77 current_zeo_port += 1
78 output += snippet_zeo % dict(
79 zeo_id=zeo_id,
80 zeo_port=current_zeo_port,
81 storage_list='\n'.join(storage_list)
82 )
83 part_list.extend([
84 "zeo-instance-%s" % zeo_id,
85 "logrotate-entry-zeo-%s" % zeo_id
86 ])
87
88 zeo_connection_list = []
89 a = zeo_connection_list.append
90 for k, v in zope_connection_dict.iteritems():
91 a(' zeo-cache-size=%(zeo-cache-size)s zope-cache-size=%(zope-cache-size)s server=%(server)s mount-point=%(mount-point)s storage-name=%(storage-name)s' % v)
92 zeo_connection_string = '\n'.join(zeo_connection_list)
93 zope_dict.update(
94 timezone=json_data['timezone'],
95 zeo_connection_string=zeo_connection_string
96 )
97 # always one distribution node
98 current_zope_port += 1
99 snippet_zope = open(self.options['snippet-zope']).read()
100 zope_id = 'zope-distribution'
101 part_list.append(zope_id)
102 part_list.append('logrotate-entry-%s' % zope_id)
103 output += snippet_zope % dict(zope_thread_amount=1, zope_id=zope_id,
104 zope_port=current_zope_port, zope_timeserver=True, **zope_dict)
105 # always one admin node
106 current_zope_port += 1
107 zope_id = 'zope-admin'
108 part_list.append(zope_id)
109 part_list.append('logrotate-entry-%s' % zope_id)
110 output += snippet_zope % dict(zope_thread_amount=1, zope_id=zope_id,
111 zope_port=current_zope_port, zope_timeserver=False, **zope_dict)
112 # handle activity key
113 for q in range(1, json_data['activity']['zopecount'] + 1):
114 current_zope_port += 1
115 part_name = 'zope-activity-%s' % q
116 part_list.append(part_name)
117 part_list.append('logrotate-entry-%s' % part_name)
118 output += snippet_zope % dict(zope_thread_amount=1, zope_id=part_name,
119 zope_port=current_zope_port, zope_timeserver=True, **zope_dict)
120 # handle backend key
121 snippet_backend = open(self.options['snippet-backend']).read()
122 publish_url_list = []
123 for backend_name, backend_configuration in json_data['backend'].iteritems():
124 haproxy_backend_list = []
125 for q in range(1, backend_configuration['zopecount'] + 1):
126 current_zope_port += 1
127 part_name = 'zope-%s-%s' % (backend_name, q)
128 part_list.append(part_name)
129 part_list.append('logrotate-entry-%s' % part_name)
130 output += snippet_zope % dict(
131 zope_thread_amount=backend_configuration['thread-amount'],
132 zope_id=part_name, zope_port=current_zope_port, zope_timeserver=False,
133 **zope_dict)
134 haproxy_backend_list.append('${%(part_name)s:ip}:${%(part_name)s:port}' % dict(part_name=part_name))
135 # now generate backend access
136 current_apache_port += 1
137 current_haproxy_port += 1
138 part_list.append('apache-%(backend_name)s ca-apache-%(backend_name)s logrotate-entry-apache-%(backend_name)s haproxy-%(backend_name)s' % dict(backend_name=backend_name))
139 backend_dict = dict(
140 backend_name=backend_name,
141 apache_port=current_apache_port,
142 haproxy_port=current_haproxy_port,
143 access_control_string=backend_configuration['access-control-string'],
144 maxconn=backend_configuration['maxconn'],
145 server_check_path='/%s/getId' % site_id,
146 haproxy_backend_list=' '.join(haproxy_backend_list)
147 )
148 publish_url_list.append('url-%(backend_name)s = https://[${apache-%(backend_name)s:ip}]:${apache-%(backend_name)s:port}' % dict(
149 backend_name=backend_name))
150 output += snippet_backend % backend_dict
151 output += SECTION_BACKEND_PUBLISHER + '\n'
152 output += '\n'.join(publish_url_list)
153 part_list.append('publish-apache-backend-list')
154 prepend = open(self.options['snippet-master']).read() % dict(
155 part_list=' \n'.join([' '+q for q in part_list]),
156 known_tid_storage_identifier_dict=known_tid_storage_identifier_dict,
157 haproxy_section="haproxy-%s" % backend_name,
158 zope_section=zope_id,
159 site_id=site_id,
160 **self.parameter_dict
161 )
162 output = prepend + output
163 with open(self.options['output'], 'w') as f:
164 f.write(output)
165
166 def _install(self):
167 if not os.path.exists(self.dirname):
168 os.mkdir(self.dirname)
169 if not "json" in self.parameter_dict:
170 # no json transimtted, nothing to do
171 with open(self.options['output'], 'w') as f:
172 f.write("[buildout]\nparts =\n")
173 else:
174 try:
175 self._generateRealTemplate()
176 except Exception:
177 print 'Ignored issue during template generation:\n%s' % \
178 traceback.format_exc()
179 return [self.dirname]