Merge master branch to get tar component.
[slapos.git] / slapos / recipe / generic_mysql / __init__.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 GenericBaseRecipe
28 import os
29
30 class Recipe(GenericBaseRecipe):
31
32 def _options(self, options):
33 options['password'] = self.generatePassword()
34 if 'test-database' in options:
35 options['test-password'] = self.generatePassword()
36 options.setdefault('parallel-test-database-amount', '0')
37 for x in xrange(int(options['parallel-test-database-amount'])):
38 options['test-password-%s' % x] = self.generatePassword()
39
40 def install(self):
41 path_list = []
42
43 template_filename = self.getTemplateFilename('my.cnf.in')
44
45 mysql_binary = self.options['mysql-binary']
46 socket = self.options['socket']
47
48 if 'ip' in self.options:
49 networking = 'port = %s\nbind-address = %s' % (
50 self.options['port'],
51 self.options['ip'],
52 )
53 else:
54 networking = 'skip-networking'
55
56 mysql_conf_file = self.createFile(
57 self.options['conf-file'],
58 self.substituteTemplate(template_filename, {
59 'networking': networking,
60 'data_directory': self.options['data-directory'],
61 'pid_file': self.options['pid-file'],
62 'socket': self.options['socket'],
63 'error_log': self.options['error-log'],
64 'slow_query_log': self.options['slow-query-log'],
65 })
66 )
67 path_list.append(mysql_conf_file)
68
69 mysql_script_list = []
70
71 # user defined functions
72 mysql_script_list.append(self.substituteTemplate(
73 self.getTemplateFilename('mysql-init-function.sql.in'),
74 {
75 }
76 ))
77 # real database
78 mysql_script_list.append(self.substituteTemplate(
79 self.getTemplateFilename('initmysql.sql.in'),
80 {
81 'mysql_database': self.options['database'],
82 'mysql_user': self.options['user'],
83 'mysql_password': self.options['password']
84 }
85 ))
86 # default test database
87 if 'test-database' in self.options:
88 mysql_script_list.append(self.substituteTemplate(
89 self.getTemplateFilename('initmysql.sql.in'),
90 {
91 'mysql_database': self.options['test-database'],
92 'mysql_user': self.options['test-user'],
93 'mysql_password': self.options['test-password']
94 }
95 ))
96 # parallel test databases
97 for x in xrange(int(self.options['parallel-test-database-amount'])):
98 mysql_script_list.append(self.substituteTemplate(
99 self.getTemplateFilename('initmysql.sql.in'),
100 {
101 'mysql_database': self.options['mysql-test-database-base'] + '_%s' % x,
102 'mysql_user': self.options['mysql-test-user-base'] + '_%s' % x,
103 'mysql_password': self.options['test-password-%s' % x]
104 }
105 ))
106 mysql_script_list.append('EXIT')
107 mysql_script = '\n'.join(mysql_script_list)
108
109 mysql_upgrade_binary = self.options['mysql-upgrade-binary']
110 mysql_update = self.createPythonScript(
111 self.options['update-wrapper'],
112 '%s.mysql.updateMysql' % __name__,
113 [dict(
114 mysql_script=mysql_script,
115 mysql_binary=mysql_binary,
116 mysql_upgrade_binary=mysql_upgrade_binary,
117 socket=socket,
118 )]
119 )
120 path_list.append(mysql_update)
121
122 mysqld_binary = self.options['mysqld-binary']
123 mysqld = self.createPythonScript(
124 self.options['wrapper'],
125 '%s.mysql.runMysql' % __name__,
126 [dict(
127 mysql_base_directory=self.options['mysql-base-directory'],
128 mysql_install_binary=self.options['mysql-install-binary'],
129 mysqld_binary=mysqld_binary,
130 data_directory=self.options['data-directory'],
131 mysql_binary=mysql_binary,
132 socket=socket,
133 configuration_file=mysql_conf_file,
134 )]
135 )
136 path_list.append(mysqld)
137 # TODO: move to a separate recipe (ack'ed by Cedric)
138 if 'backup-script' in self.options:
139 # backup configuration
140 full_backup = self.options['full-backup-directory']
141 incremental_backup = self.options['incremental-backup-directory']
142 innobackupex_argument_list = [self.options['perl-binary'],
143 self.options['innobackupex-binary'],
144 '--defaults-file=%s' % mysql_conf_file,
145 '--socket=%s' % socket.strip(), '--user=root',
146 '--ibbackup=%s'% self.options['xtrabackup-binary']]
147 environment = dict(PATH='%s' % self.options['bin-directory'])
148 innobackupex_incremental = self.createPythonScript(self.options['innobackupex-incremental'], 'slapos.recipe.librecipe.execute.executee', [innobackupex_argument_list + ['--incremental'], environment])
149 path_list.append(innobackupex_incremental)
150 innobackupex_full = self.createPythonScript(self.options['innobackupex-full'], 'slapos.recipe.librecipe.execute.executee', [innobackupex_argument_list, environment])
151 path_list.append(innobackupex_full)
152 backup_controller = self.createPythonScript(self.options['backup-script'], __name__ + '.innobackupex.controller', [innobackupex_incremental, innobackupex_full, full_backup, incremental_backup])
153 path_list.append(backup_controller)
154 # TODO: move to a separate recipe (ack'ed by Cedric)
155 # percona toolkit (formerly known as maatkit) installation
156 for pt_script_name in (
157 'pt-archiver',
158 'pt-config-diff',
159 'pt-deadlock-logger',
160 'pt-duplicate-key-checker',
161 'pt-fifo-split',
162 'pt-find',
163 'pt-fk-error-logger',
164 'pt-heartbeat',
165 'pt-index-usage',
166 'pt-kill',
167 'pt-log-player',
168 'pt-online-schema-change',
169 'pt-query-advisor',
170 'pt-query-digest',
171 'pt-show-grants',
172 'pt-slave-delay',
173 'pt-slave-find',
174 'pt-slave-restart',
175 'pt-table-checksum',
176 'pt-table-sync',
177 'pt-tcp-model',
178 'pt-trend',
179 'pt-upgrade',
180 'pt-variable-advisor',
181 'pt-visual-explain',
182 ):
183 option_name = pt_script_name + '-binary'
184 if option_name not in self.options:
185 continue
186 pt_argument_list = [self.options['perl-binary'],
187 self.options[option_name],
188 '--defaults-file=%s' % mysql_conf_file,
189 '--socket=%s' % socket.strip(), '--user=root',
190 ]
191 pt_exe = self.createPythonScript(os.path.join(self.options['bin-directory'], pt_script_name), 'slapos.recipe.librecipe.execute.executee', [pt_argument_list, environment])
192 path_list.append(pt_exe)
193
194 return path_list