Deprecation warning
[slapos.git] / slapos / recipe / lamp / __init__.py
1 ##############################################################################
2 #
3 # Copyright (c) 2010 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 BaseSlapRecipe
28 import os
29 import shutil
30 import pkg_resources
31 import zc.buildout
32 import sys
33 import zc.recipe.egg
34 import urlparse
35
36 # Warning : this recipe is deprecated and has been replaced by apachephp.
37
38 class BaseRecipe(BaseSlapRecipe):
39 def getTemplateFilename(self, template_name):
40 return pkg_resources.resource_filename(__name__,
41 'template/%s' % template_name)
42
43 def installMysqlServer(self, ip=None, port=None):
44 if ip is None:
45 ip = self.getLocalIPv4Address()
46 if port is None:
47 port = '3306'
48 mysql_conf = dict(
49 ip=ip,
50 data_directory=os.path.join(self.data_root_directory,
51 'mysql'),
52 tcp_port=port,
53 pid_file=os.path.join(self.run_directory, 'mysqld.pid'),
54 socket=os.path.join(self.run_directory, 'mysqld.sock'),
55 error_log=os.path.join(self.log_directory, 'mysqld.log'),
56 slow_query_log=os.path.join(self.log_directory,
57 'mysql-slow.log'),
58 database='appdb',
59 user='appuser',
60 password=self.generatePassword(),
61 )
62 self._createDirectory(mysql_conf['data_directory'])
63
64 mysql_conf_path = self.createConfigurationFile("my.cnf",
65 self.substituteTemplate(pkg_resources.resource_filename(__name__,
66 'template/my.cnf.in'), mysql_conf))
67
68 mysql_script = pkg_resources.resource_string(__name__,
69 'template/mysqlinit.sql.in') % mysql_conf
70 self.path_list.extend(zc.buildout.easy_install.scripts([('mysql_update',
71 __name__ + '.mysql', 'updateMysql')], self.ws,
72 sys.executable, self.wrapper_directory, arguments=[dict(
73 mysql_script=mysql_script,
74 mysql_binary=self.options['mysql_binary'].strip(),
75 mysql_upgrade_binary=self.options['mysql_upgrade_binary'].strip(),
76 socket=mysql_conf['socket'],
77 )]))
78 self.path_list.extend(zc.buildout.easy_install.scripts([('mysqld',
79 __name__ + '.mysql', 'runMysql')], self.ws,
80 sys.executable, self.wrapper_directory, arguments=[dict(
81 mysql_install_binary=self.options['mysql_install_binary'].strip(),
82 mysqld_binary=self.options['mysqld_binary'].strip(),
83 data_directory=mysql_conf['data_directory'].strip(),
84 mysql_binary=self.options['mysql_binary'].strip(),
85 socket=mysql_conf['socket'].strip(),
86 configuration_file=mysql_conf_path,
87 )]))
88 self.path_list.extend([mysql_conf_path])
89 return dict(
90 mysql_host=mysql_conf['ip'],
91 mysql_port=mysql_conf['tcp_port'],
92 mysql_user=mysql_conf['user'],
93 mysql_password=mysql_conf['password'],
94 mysql_database=mysql_conf['database'],
95 )
96
97 def createHtdocs(self, source, document_root):
98 source = self.options['source'].strip()
99 document_root = self.createDataDirectory('htdocs')
100 for p in os.listdir(document_root):
101 path = os.path.join(document_root, p)
102 if os.path.isdir(path):
103 shutil.rmtree(path)
104 else:
105 os.unlink(path)
106 for p in os.listdir(source):
107 path = os.path.join(source, p)
108 if os.path.isdir(path):
109 shutil.copytree(path, os.path.join(document_root, p))
110 else:
111 shutil.copy2(path, os.path.join(document_root, p))
112
113 def installApache(self, document_root, ip=None, port=None):
114 if ip is None:
115 ip=self.getGlobalIPv6Address()
116 if port is None:
117 port = '9080'
118 apache_config = dict(
119 pid_file=os.path.join(self.run_directory, 'httpd.pid'),
120 lock_file=os.path.join(self.run_directory, 'httpd.lock'),
121 ip=ip,
122 port=port,
123 error_log=os.path.join(self.log_directory, 'httpd-error.log'),
124 access_log=os.path.join(self.log_directory, 'httpd-access.log'),
125 document_root=document_root,
126 php_ini_dir=self.etc_directory
127 )
128 config_file = self.createConfigurationFile('httpd.conf',
129 self.substituteTemplate(pkg_resources.resource_filename(__name__,
130 'template/apache.in'), apache_config))
131 self.path_list.append(config_file)
132 php_ini = pkg_resources.resource_filename(__name__, 'template/php.ini.in')
133 if self.options.has_key('php_ini'):
134 php_ini = os.path.join(self.options['php_ini'], 'php.ini.in')
135 self.path_list.append(self.createConfigurationFile('php.ini',
136 self.substituteTemplate(php_ini, dict(tmp_directory=self.tmp_directory))))
137 self.path_list.extend(zc.buildout.easy_install.scripts([(
138 'httpd',
139 __name__ + '.apache', 'runApache')], self.ws,
140 sys.executable, self.wrapper_directory, arguments=[
141 dict(
142 required_path_list=[],
143 binary=self.options['httpd_binary'],
144 config=config_file
145 )
146 ]))
147 return 'http://[%s]:%s' % (ip, port)
148
149 def createConfiguration(self, template, document_root, destination, d):
150 directory = os.path.dirname(destination)
151 file = os.path.basename(destination)
152 path = document_root
153 if directory:
154 path = os.path.join(document_root, directory)
155 if not os.path.exists(path):
156 os.makedirs(path)
157 destination = os.path.join(path, file)
158 open(destination, 'w').write(open(template, 'r').read() % d)
159
160 def configureInstallation(self, document_root, url, mysql_conf):
161 """Start process which can launch python scripts, move or remove files or
162 directories when installing software.
163 """
164 if not self.options.has_key('delete') and not self.options.has_key('rename') and not\
165 self.options.has_key('chmod') and not self.options.has_key('script'):
166 return ""
167 delete = []
168 chmod = []
169 data = []
170 rename = []
171 rename_list = ""
172 argument = [self.options['lampconfigure_directory'].strip(),
173 "-H", mysql_conf['mysql_host'], "-P", mysql_conf['mysql_port'],
174 "-p", mysql_conf['mysql_password'], "-u", mysql_conf['mysql_user']]
175 if not self.options.has_key('file_token'):
176 argument = argument + ["-d", mysql_conf['mysql_database'],
177 "--table", self.options['table_name'].strip(), "--cond",
178 self.options['constraint'].strip()]
179 else:
180 argument = argument + ["-f", self.options['file_token'].strip()]
181 argument += ["-t", document_root]
182
183 if self.options.has_key('delete'):
184 delete = ["delete"]
185 for fname in self.options['delete'].split(','):
186 delete.append(fname.strip())
187 if self.options.has_key('rename'):
188 for fname in self.options['rename'].split(','):
189 if fname.find("=>") < 0:
190 old_name = fname
191 fname = []
192 fname.append(old_name)
193 fname.append(old_name + '-' + mysql_conf['mysql_user'])
194 else:
195 fname = fname.split("=>")
196 cmd = ["rename"]
197 if self.options.has_key('rename_chmod'):
198 cmd += ["--chmod", self.options['rename_chmod'].strip()]
199 rename.append(cmd + [fname[0].strip(), fname[1].strip()])
200 rename_list += fname[0] + " to " + fname[1] + " "
201 if self.options.has_key('chmod'):
202 chmod = ["chmod", self.options['mode'].strip()]
203 for fname in self.options['chmod'].split(','):
204 chmod.append(fname.strip())
205 if self.options.has_key('script') and \
206 self.options['script'].strip().endswith(".py"):
207 data = ["run", self.options['script'].strip(), "-v", mysql_conf['mysql_database'], url, document_root]
208 self.path_list.extend(zc.buildout.easy_install.scripts(
209 [('configureInstall', __name__ + '.runner', 'executeRunner')], self.ws,
210 sys.executable, self.wrapper_directory, arguments=[argument, delete, rename,
211 chmod, data]))
212 return rename_list
213
214 class Static(BaseRecipe):
215 def _install(self):
216 self.path_list = []
217 self.requirements, self.ws = self.egg.working_set()
218 document_root = self.createDataDirectory('htdocs')
219 self.createHtdocs(self.options['source'].strip(), document_root)
220 url = self.installApache(document_root)
221 self.setConnectionDict(dict(url = url))
222 return self.path_list
223
224 class Simple(BaseRecipe):
225 def _install(self):
226 self.path_list = []
227 self.requirements, self.ws = self.egg.working_set()
228 document_root = self.createDataDirectory('htdocs')
229 self.createHtdocs(self.options['source'].strip(), document_root)
230 mysql_conf = self.installMysqlServer()
231 url = self.installApache(document_root)
232 renamed = self.configureInstallation(document_root, url, mysql_conf)
233 connectionDict = dict(
234 url=url,
235 **mysql_conf
236 )
237 if not renamed == "":
238 connectionDict['rename'] = renamed
239 self.setConnectionDict(connectionDict)
240 if self.options.has_key('template') and self.options.has_key('configuration'):
241 self.createConfiguration(self.options['template'], document_root,
242 self.options['configuration'], mysql_conf)
243 return self.path_list
244
245 class Request(BaseRecipe):
246 def _install(self):
247 self.path_list = []
248 self.requirements, self.ws = self.egg.working_set()
249 software_type = self.parameter_dict['slap_software_type']
250
251 document_root = self.createDataDirectory('htdocs')
252 self.createHtdocs(self.options['source'].strip(), document_root)
253
254 if software_type == 'Backuped':
255 davstorage = self.request(self.options['davstorage-software-url'],
256 software_type, 'Backup Server').getConnectionParameter('url')
257
258 parameters = {'remote_backup': davstorage}
259 elif software_type == 'PersonnalBackup':
260 parameters = {'remote_backup': self.parameter_dict['remote_backup']}
261 else:
262 parameters = {}
263
264 mysql = self.request(self.options['mariadb-software-url'],
265 software_type, 'MariaDB Server', partition_parameter_kw=parameters
266 ).getConnectionParameter('url')
267 mysql_parsed = urlparse.urlparse(mysql)
268
269 mysql_host, mysql_port = mysql_parsed.hostname, mysql_parsed.port
270 if mysql_parsed.scheme == 'mysqls': # Listen over stunnel
271 mysql_host, mysql_port = self.installStunnelClient(mysql_host,
272 mysql_port)
273
274 mysql_conf = dict(mysql_database=mysql_parsed.path.strip('/'),
275 mysql_user=mysql_parsed.username,
276 mysql_password=mysql_parsed.password,
277 mysql_host='%s:%s' % (mysql_host,mysql_port))
278
279 url = self.installApache(document_root)
280
281 self.setConnectionDict(dict(
282 url=url,
283 ))
284
285 self.createConfiguration(self.options['template'], document_root,
286 self.options['configuration'], mysql_conf)
287 return self.path_list
288
289 def installStunnelClient(self, remote_host, remote_port):
290 local_host = self.getLocalIPv4Address()
291 local_port = 8888
292 stunnel_conf_path = self.createConfigurationFile('stunnel.conf',
293 self.substituteTemplate(
294 self.getTemplateFilename('stunnel.conf.in'), {
295 'log': os.path.join(self.log_directory, 'stunnel.log'),
296 'pid_file': os.path.join(self.run_directory, 'stunnel.pid'),
297 'remote_host': remote_host, 'remote_port': remote_port,
298 'local_host': local_host, 'local_port': local_port,
299 }))
300 wrapper = zc.buildout.easy_install.scripts([('stunnel',
301 'slapos.recipe.librecipe.execute', 'execute')], self.ws,
302 sys.executable, self.wrapper_directory, arguments=[
303 self.options['stunnel_binary'].strip(), stunnel_conf_path]
304 )[0]
305 self.path_list.append(wrapper)
306 return (local_host, local_port,)