Package starcluster :: Package plugins :: Module mysql
[hide private]
[frames] | no frames]

Source Code for Module starcluster.plugins.mysql

  1   
  2  import posixpath 
  3  from starcluster.clustersetup import DefaultClusterSetup 
  4  from starcluster.logger import log 
  5   
  6  ndb_mgmd_template = \ 
  7  ''' 
  8  [NDBD DEFAULT] 
  9  NoOfReplicas=%(num_replicas)s 
 10  DataMemory=%(data_memory)s    # How much memory to allocate for data storage 
 11  IndexMemory=%(index_memory)s   # How much memory to allocate for index storage 
 12  [MYSQLD DEFAULT] 
 13  [NDB_MGMD DEFAULT] 
 14  [TCP DEFAULT] 
 15  # Section for the cluster management node 
 16  [NDB_MGMD] 
 17  # IP address of the management node (this system) 
 18  HostName=%(mgm_ip)s 
 19  # Section for the storage nodes 
 20  ''' 
 21   
 22  ndb_mgmd_storage = \ 
 23  ''' 
 24  [NDBD] 
 25  HostName=%(storage_ip)s 
 26  DataDir=%(data_dir)s 
 27  BackupDataDir=%(backup_data_dir)s 
 28  ''' 
 29   
 30  MY_CNF = \ 
 31  ''' 
 32  # 
 33  # The MySQL database server configuration file. 
 34  # 
 35  # You can copy this to one of: 
 36  # - "/etc/mysql/my.cnf" to set global options, 
 37  # - "~/.my.cnf" to set user-specific options. 
 38  # 
 39  # One can use all long options that the program supports. 
 40  # Run program with --help to get a list of available options and with 
 41  # --log.info-defaults to see which it would actually understand and use. 
 42  # 
 43  # For explanations see 
 44  # http://dev.mysql.com/doc/mysql/en/server-system-variables.html 
 45   
 46  # This will be passed to all mysql clients 
 47  # It has been reported that passwords should be enclosed with ticks/quotes 
 48  # especially if they contain "#" chars... 
 49  # Remember to edit /etc/mysql/debian.cnf when changing the socket location. 
 50  [client] 
 51  port            = 3306 
 52  socket          = /var/run/mysqld/mysqld.sock 
 53   
 54  # Here is entries for some specific programs 
 55  # The following values assume you have at least 32M ram 
 56   
 57  # This was formally known as [safe_mysqld]. Both versions are currently parsed. 
 58  [mysqld_safe] 
 59  socket          = /var/run/mysqld/mysqld.sock 
 60  nice            = 0 
 61   
 62  [mysqld] 
 63  # 
 64  # * Basic Settings 
 65  # 
 66   
 67  # 
 68  # * IMPORTANT 
 69  #   If you make changes to these settings and your system uses apparmor, you 
 70  #   may also need to also adjust /etc/apparmor.d/usr.sbin.mysqld. 
 71  # 
 72   
 73  user            = mysql 
 74  socket          = /var/run/mysqld/mysqld.sock 
 75  port            = 3306 
 76  basedir         = /usr 
 77  datadir         = /var/lib/mysql 
 78  tmpdir          = /tmp 
 79  skip-external-locking 
 80  # 
 81  # Instead of skip-networking the default is now to listen only on 
 82  # localhost which is more compatible and is not less secure. 
 83  bind-address            = 127.0.0.1 
 84  # 
 85  # * Fine Tuning 
 86  # 
 87  key_buffer              = 16M 
 88  max_allowed_packet      = 16M 
 89  thread_stack            = 192K 
 90  thread_cache_size       = 8 
 91  # This replaces the startup script and checks MyISAM tables if needed 
 92  # the first time they are touched 
 93  myisam-recover         = BACKUP 
 94  #max_connections        = 100 
 95  #table_cache            = 64 
 96  #thread_concurrency     = 10 
 97  # 
 98  # * Query Cache Configuration 
 99  # 
100  query_cache_limit       = 1M 
101  query_cache_size        = 16M 
102  # 
103  # * Logging and Replication 
104  # 
105  # Both location gets rotated by the cronjob. 
106  # Be aware that this log type is a performance killer. 
107  # As of 5.1 you can enable the log at runtime! 
108  #general_log_file        = /var/log/mysql/mysql.log 
109  #general_log             = 1 
110   
111  log_error                = /var/log/mysql/error.log 
112   
113  # Here you can see queries with especially long duration 
114  #log_slow_queries       = /var/log/mysql/mysql-slow.log 
115  #long_query_time = 2 
116  #log-queries-not-using-indexes 
117  # 
118  # The following can be used as easy to replay backup logs or for replication. 
119  # note: if you are setting up a replication slave, see README.Debian about 
120  #       other settings you may need to change. 
121  #server-id              = 1 
122  #log_bin                        = /var/log/mysql/mysql-bin.log 
123  expire_logs_days        = 10 
124  max_binlog_size         = 100M 
125  #binlog_do_db           = include_database_name 
126  #binlog_ignore_db       = include_database_name 
127  # 
128  # * InnoDB 
129  # 
130  # InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/. 
131  # Read the manual for more InnoDB related options. There are many! 
132  # 
133  # * Security Features 
134  # 
135  # Read the manual, too, if you want chroot! 
136  # chroot = /var/lib/mysql/ 
137  # 
138  # For generating SSL certificates I recommend the OpenSSL GUI "tinyca". 
139  # 
140  # ssl-ca=/etc/mysql/cacert.pem 
141  # ssl-cert=/etc/mysql/server-cert.pem 
142  # ssl-key=/etc/mysql/server-key.pem 
143   
144  # Cluster Configuration 
145  ndbcluster 
146  # IP address of management node 
147  ndb-connectstring=%(mgm_ip)s 
148   
149  [mysqldump] 
150  quick 
151  quote-names 
152  max_allowed_packet      = 16M 
153   
154  [mysql] 
155  #no-auto-rehash # faster start of mysql but no tab completion 
156   
157  [isamchk] 
158  key_buffer              = 16M 
159   
160  [MYSQL_CLUSTER] 
161  ndb-connectstring=%(mgm_ip)s 
162   
163  # 
164  # * IMPORTANT: Additional settings that can override those from this file! 
165  #   The files must end with '.cnf', otherwise they'll be ignored. 
166  # 
167  !includedir /etc/mysql/conf.d/ 
168  ''' 
169   
170   
171 -class MysqlCluster(DefaultClusterSetup):
172 """ 173 This plugin configures a mysql cluster on StarCluster 174 Author: Marc Resnick 175 176 Steps for mysql-cluster to work: 177 1. mkdir -p /var/lib/mysql-cluster/backup 178 2. chown -R mysql:mysql /var/lib/mysql-cluster/ 179 3. generate ndb-mgmd for master 180 4. generate my.cnf for data nodes 181 5. /etc/init.d/mysql-ndb-mgm restart on master 182 6. pkill -9 mysql on data nodes 183 7. /etc/init.d/mysql start on data nodes 184 8. /etc/init.d/mysql-ndb restart on data nodes 185 186 Correction to above, do this: 187 1. define plugin section in config named mysql 188 2. start cluster mysql (will fail) 189 3. starcluster runplugin mysql mysql 190 """
191 - def __init__(self, num_replicas, data_memory, index_memory, dump_file, 192 dump_interval, dedicated_query, num_data_nodes):
193 super(MysqlCluster, self).__init__() 194 self._num_replicas = int(num_replicas) 195 self._data_memory = data_memory 196 self._index_memory = index_memory 197 self._dump_file = dump_file 198 self._dump_interval = dump_interval 199 self._dedicated_query = dedicated_query.lower() == 'true' 200 self._num_data_nodes = int(num_data_nodes)
201
202 - def _install_mysql_cluster(self, node):
203 preseedf = '/tmp/mysql-preseed.txt' 204 mysqlpreseed = node.ssh.remote_file(preseedf, 'w') 205 preseeds = """\ 206 mysql-server mysql-server/root_password select 207 mysql-server mysql-server/root_password seen true 208 mysql-server mysql-server/root_password_again select 209 mysql-server mysql-server/root_password_again seen true 210 """ 211 mysqlpreseed.write(preseeds) 212 mysqlpreseed.close() 213 node.ssh.execute('debconf-set-selections < %s' % mysqlpreseed.name) 214 node.ssh.execute('rm %s' % mysqlpreseed.name) 215 node.apt_install('mysql-cluster-server')
216
217 - def _backup_and_reset(self, node):
218 nconn = node.ssh 219 nconn.execute('pkill -9 mysql; pkill -9 ndb', 220 ignore_exit_status=True) 221 nconn.execute('mkdir -p /var/lib/mysql-cluster/BACKUP') 222 nconn.execute('chown -R mysql:mysql /var/lib/mysql-cluster')
223
224 - def _write_my_cnf(self, node):
225 nconn = node.ssh 226 my_cnf = nconn.remote_file('/etc/mysql/my.cnf') 227 my_cnf.write(self.generate_my_cnf()) 228 my_cnf.close()
229
230 - def run(self, nodes, master, user, user_shell, volumes):
231 log.info("Installing mysql-cluster-server on all nodes...") 232 for node in nodes: 233 self.pool.simple_job(self._install_mysql_cluster, (node), 234 jobid=node.alias) 235 self.pool.wait(len(nodes)) 236 mconn = master.ssh 237 mconn.execute('rm -f /usr/mysql-cluster/*') 238 # Get IPs for all nodes 239 self.mgm_ip = master.private_ip_address 240 if not self._dedicated_query: 241 self.storage_ips = [x.private_ip_address for x in nodes[1:]] 242 self.query_ips = self.storage_ips 243 self.data_nodes = nodes[1:] 244 self.query_nodes = nodes 245 else: 246 self.data_nodes = nodes[1:self._num_data_nodes + 1] 247 self.query_nodes = nodes[self._num_data_nodes + 1:] 248 self.query_nodes.append(master) 249 self.storage_ips = [x.private_ip_address for x in self.data_nodes] 250 self.query_ips = [x.private_ip_address for x in self.query_nodes] 251 # Create backup dir and change ownership of mysql-cluster dir 252 log.info('Backing up and stopping all mysql processes on all nodes') 253 for node in nodes: 254 self.pool.simple_job(self._backup_and_reset, (node), 255 jobid=node.alias) 256 self.pool.wait(len(nodes)) 257 # Generate and place ndb_mgmd configuration file 258 log.info('Generating ndb_mgmd.cnf...') 259 ndb_mgmd = mconn.remote_file('/etc/mysql/ndb_mgmd.cnf') 260 ndb_mgmd.write(self.generate_ndb_mgmd()) 261 ndb_mgmd.close() 262 # Generate and place my.cnf configuration file on each data node 263 log.info('Generating my.cnf on all nodes') 264 for node in nodes: 265 self.pool.simple_job(self._write_my_cnf, (node), jobid=node.alias) 266 self.pool.wait(len(nodes)) 267 # Restart mysql-ndb-mgm on master 268 log.info('Restarting mysql-ndb-mgm on master node...') 269 mconn.execute('/etc/init.d/mysql-ndb-mgm restart') 270 # Start mysqld-ndb on data nodes 271 log.info('Restarting mysql-ndb on all data nodes...') 272 for node in self.data_nodes: 273 self.pool.simple_job(node.ssh.execute, 274 ('/etc/init.d/mysql-ndb restart'), 275 jobid=node.alias) 276 self.pool.wait(len(self.data_nodes)) 277 # Start mysql on query nodes 278 log.info('Starting mysql on all query nodes') 279 for node in self.query_nodes: 280 self.pool.simple_job(node.ssh.execute, 281 ('/etc/init.d/mysql restart'), 282 dict(ignore_exit_status=True), 283 jobid=node.alias) 284 self.pool.wait(len(self.query_nodes)) 285 # Import sql dump 286 dump_file = self._dump_file 287 dump_dir = '/mnt/mysql-cluster-backup' 288 if posixpath.isabs(self._dump_file): 289 dump_dir, dump_file = posixpath.split(self._dump_file) 290 else: 291 log.warn("%s is not an absolute path, defaulting to %s" % 292 (self._dump_file, posixpath.join(dump_dir, dump_file))) 293 name, ext = posixpath.splitext(dump_file) 294 sc_path = posixpath.join(dump_dir, name + '.sc' + ext) 295 orig_path = posixpath.join(dump_dir, dump_file) 296 if not mconn.isdir(dump_dir): 297 log.info("Directory %s does not exist, creating..." % dump_dir) 298 mconn.makedirs(dump_dir) 299 if mconn.isfile(sc_path): 300 mconn.execute('mysql < %s' % sc_path) 301 elif mconn.isfile(orig_path): 302 mconn.execute('mysql < %s' % orig_path) 303 else: 304 log.info('No dump file found, not importing.') 305 log.info('Adding MySQL dump cronjob to master node') 306 cronjob = self.generate_mysqldump_crontab(sc_path) 307 mconn.remove_lines_from_file('/etc/crontab', '#starcluster-mysql') 308 crontab_file = mconn.remote_file('/etc/crontab', 'a') 309 crontab_file.write(cronjob) 310 crontab_file.close() 311 log.info('Management Node: %s' % master.alias) 312 log.info('Data Nodes: \n%s' % '\n'.join([x.alias for x in 313 self.data_nodes])) 314 log.info('Query Nodes: \n%s' % '\n'.join([x.alias for x in 315 self.query_nodes]))
316
317 - def generate_ndb_mgmd(self):
318 ndb_mgmd = ndb_mgmd_template % {'num_replicas': self._num_replicas, 319 'data_memory': self._data_memory, 320 'index_memory': self._index_memory, 321 'mgm_ip': self.mgm_ip} 322 for x in self.storage_ips: 323 ctx = {'storage_ip': x, 324 'data_dir': '/var/lib/mysql-cluster', 325 'backup_data_dir': '/var/lib/mysql-cluster'} 326 ndb_mgmd += ndb_mgmd_storage % ctx 327 ndb_mgmd += '\n' 328 if self._dedicated_query: 329 for x in self.query_nodes: 330 ndb_mgmd += '[MYSQLD]\nHostName=%s\n' % x.private_ip_address 331 else: 332 for x in self.query_nodes: 333 ndb_mgmd += '[MYSQLD]\n' 334 return ndb_mgmd
335
336 - def generate_my_cnf(self):
337 return MY_CNF % dict(mgm_ip=self.mgm_ip)
338
339 - def generate_mysqldump_crontab(self, path):
340 crontab = ( 341 '\n*/%(dump_interval)s * * * * root ' + 342 'mysql --batch --skip-column-names --execute="show databases"' + 343 " | egrep -v '(mysql|information_schema)' | " + 344 "xargs mysqldump --add-drop-table --add-drop-database -Y -B" + 345 '> %(loc)s #starcluster-mysql\n' 346 ) % {'dump_interval': self._dump_interval, 'loc': path} 347 return crontab
348