2
# -*- mode: python; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
# Copyright (C) 2010,2011 Patrick Crews
7
# This program is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, write to the Free Software
19
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
""" drizzled.py: code to allow a serverManager
23
to provision and start up a drizzled server object
30
from lib.server_mgmt.server import Server
32
class drizzleServer(Server):
33
""" represents a drizzle server, its possessions
34
(datadir, ports, etc), and methods for controlling
37
TODO: create a base server class that contains
38
standard methods from which we can inherit
39
Currently there are definitely methods / attr
44
def __init__( self, name, server_manager, code_tree, default_storage_engine
45
, server_options, requester, test_executor, workdir_root):
46
super(drizzleServer, self).__init__( name
49
, default_storage_engine
54
self.preferred_base_port = 9306
57
self.drizzledump = self.code_tree.drizzledump
58
self.drizzle_client = self.code_tree.drizzle_client
59
self.drizzleimport = self.code_tree.drizzleimport
60
self.drizzleslap = self.code_tree.drizzleslap
61
self.server_path = self.code_tree.drizzle_server
62
self.drizzle_client_path = self.code_tree.drizzle_client
63
self.schemawriter = self.code_tree.schemawriter
66
self.port_block = self.system_manager.port_manager.get_port_block( self.name
67
, self.preferred_base_port
69
self.master_port = self.port_block[0]
70
self.drizzle_tcp_port = self.port_block[1]
71
self.mc_port = self.port_block[2]
72
self.pbms_port = self.port_block[3]
73
self.rabbitmq_node_port = self.port_block[4]
74
self.json_server_port = self.port_block[5]
76
# Generate our working directories
77
self.dirset = {'var_%s' %(self.name): {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
81
,'master-data': {'local': { 'test':None
87
self.workdir = self.system_manager.create_dirset( workdir_root
89
self.vardir = self.workdir
90
self.tmpdir = os.path.join(self.vardir,'tmp')
91
self.rundir = os.path.join(self.vardir,'run')
92
self.logdir = os.path.join(self.vardir,'log')
93
self.datadir = os.path.join(self.vardir,'master-data')
95
self.error_log = os.path.join(self.logdir,'error.log')
96
self.pid_file = os.path.join(self.rundir,('%s.pid' %(self.name)))
97
self.socket_file = os.path.join(self.vardir, ('%s.sock' %(self.name)))
98
if len(self.socket_file) > 107:
99
# MySQL has a limitation of 107 characters for socket file path
100
# we copy the mtr workaround of creating one in /tmp
101
self.logging.verbose("Default socket file path: %s" %(self.socket_file))
102
self.socket_file = "/tmp/%s_%s.%s.sock" %(self.system_manager.uuid
105
self.logging.verbose("Changing to alternate: %s" %(self.socket_file))
106
self.timer_file = os.path.join(self.logdir,('timer'))
108
# Do magic to create a config file for use with the slave
110
self.slave_config_file = os.path.join(self.logdir,'slave.cnf')
111
self.create_slave_config_file()
113
self.snapshot_path = os.path.join(self.tmpdir,('snapshot_%s' %(self.master_port)))
114
# We want to use --secure-file-priv = $vardir by default
115
# but there are times / tools when we need to shut this off
116
if self.no_secure_file_priv:
117
self.secure_file_string = ''
119
self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
120
self.user_string = '--user=root'
122
self.initialize_databases()
123
self.take_db_snapshot()
125
self.logging.debug_class(self)
128
""" We print out some general useful info """
129
report_values = [ 'name'
134
, 'rabbitmq_node_port'
138
self.logging.info("%s server:" %(self.owner))
139
for key in report_values:
140
value = vars(self)[key]
141
self.logging.info("%s: %s" %(key.upper(), value))
143
def get_start_cmd(self):
144
""" Return the command string that will start up the server
145
as desired / intended
149
server_args = [ self.process_server_options()
150
, "--mysql-protocol.port=%d" %(self.master_port)
151
, "--mysql-protocol.connect-timeout=60"
152
, "--innodb.data-file-path=ibdata1:20M:autoextend"
153
, "--sort-buffer-size=256K"
154
, "--max-heap-table-size=1M"
155
, "--mysql-unix-socket-protocol.path=%s" %(self.socket_file)
156
, "--pid-file=%s" %(self.pid_file)
157
, "--drizzle-protocol.port=%d" %(self.drizzle_tcp_port)
158
, "--default-storage-engine=%s" %(self.default_storage_engine)
159
, "--datadir=%s" %(self.datadir)
160
, "--tmpdir=%s" %(self.tmpdir)
161
, self.secure_file_string
166
server_args.append('--gdb')
167
return self.system_manager.handle_gdb_reqs(self, server_args)
169
return "%s %s %s & " % ( self.cmd_prefix
171
, " ".join(server_args)
175
def get_stop_cmd(self):
176
""" Return the command that will shut us down """
178
return "%s --user=root --port=%d --connect-timeout=5 --silent --password= --shutdown " %(self.drizzle_client_path, self.master_port)
181
def get_ping_cmd(self):
182
"""Return the command string that will
183
ping / check if the server is alive
187
return "%s --ping --port=%d --user=root" % (self.drizzle_client_path, self.master_port)
189
def is_started(self):
190
""" Determine if the server is up and running -
191
this may vary from server type to server type
195
# We experiment with waiting for a pid file to be created vs. pinging
196
# This is what test-run.pl does and it helps us pass logging_stats tests
197
# while not self.ping_server(server, quiet=True) and timer != timeout:
199
return self.system_manager.find_path( [self.pid_file]
202
def create_slave_config_file(self):
203
""" Create a config file suitable for use
204
with the slave-plugin. This allows
205
us to tie other servers in easily
209
config_data = [ "[master1]"
210
, "master-host=127.0.0.1"
211
, "master-port=%d" %self.master_port
214
, "max-reconnects=100"
215
#, "seconds-between-reconnects=20"
217
outfile = open(self.slave_config_file,'w')
218
for line in config_data:
219
outfile.write("%s\n" %(line))
223
def get_innodb_version(self):
224
""" SHOW VARIABLES LIKE innodb_version
225
mostly used as a check to ensure if a
226
test should/shouldn't be executed
230
query = "SHOW VARIABLES LIKE 'innodb_version'"
231
retcode, result = execute_query(query, self)
232
return retcode, result
234
def get_xtradb_version(self):
235
""" Return the xtradb version or None """
237
retcode, result = self.get_innodb_version()
238
# result format = (('innodb_version', '1.1.6-20.1'),)
240
innodb_version = result[0][1]
241
split_data = innodb_version.split('-')
242
if len(split_data) > 1:
243
return split_data[-1]