2
# -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
# Copyright (C) 2010 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
31
class drizzleServer():
32
""" represents a drizzle server, its possessions
33
(datadir, ports, etc), and methods for controlling
36
TODO: create a base server class that contains
37
standard methods from which we can inherit
38
Currently there are definitely methods / attr
46
, default_storage_engine
50
self.skip_keys = [ 'server_manager'
53
, 'preferred_base_port'
54
, 'no_secure_file_priv'
55
, 'secure_file_string'
58
self.debug = server_manager.debug
59
self.verbose = server_manager.verbose
61
self.owner = requester
62
self.server_options = server_options
63
self.default_storage_engine = default_storage_engine
64
self.server_manager = server_manager
65
# We register with server_manager asap
66
self.server_manager.log_server(self, requester)
68
self.system_manager = self.server_manager.system_manager
69
self.valgrind = self.system_manager.valgrind
70
self.gdb = self.system_manager.gdb
72
self.valgrind_time_buffer = 10
74
self.valgrind_time_buffer = 1
75
self.cmd_prefix = self.system_manager.cmd_prefix
76
self.logging = self.system_manager.logging
77
self.no_secure_file_priv = self.server_manager.no_secure_file_priv
78
self.code_tree = self.system_manager.code_tree
79
self.preferred_base_port = 9306
81
self.status = 0 # stopped, 1 = running
83
self.failed_test = 0 # was the last test a failure? our state is suspect
84
self.server_start_timeout = 60 * self.valgrind_time_buffer
87
self.port_block = self.system_manager.port_manager.get_port_block( self.name
88
, self.preferred_base_port
90
self.master_port = self.port_block[0]
91
self.drizzle_tcp_port = self.port_block[1]
92
self.mc_port = self.port_block[2]
93
self.pbms_port = self.port_block[3]
94
self.rabbitmq_node_port = self.port_block[4]
97
# Generate our working directories
98
self.dirset = { self.name : { 'var': {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
102
,'master-data': {'local': { 'test':None
109
self.workdir = self.system_manager.create_dirset( workdir_root
111
self.vardir = os.path.join(self.workdir,'var')
112
self.tmpdir = os.path.join(self.vardir,'tmp')
113
self.rundir = os.path.join(self.vardir,'run')
114
self.logdir = os.path.join(self.vardir,'log')
115
self.datadir = os.path.join(self.vardir,'master-data')
117
self.error_log = os.path.join(self.logdir,('%s.err' %(self.name)))
118
self.pid_file = os.path.join(self.rundir,('%s.pid' %(self.name)))
119
self.socket_file = os.path.join(self.vardir, ('%s.sock' %(self.name)))
120
self.timer_file = os.path.join(self.logdir,('timer'))
121
self.snapshot_path = os.path.join(self.tmpdir,('snapshot_%s' %(self.master_port)))
122
# We want to use --secure-file-priv = $vardir by default
123
# but there are times / tools when we need to shut this off
124
if self.no_secure_file_priv:
125
self.secure_file_string = ''
127
self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
128
self.user_string = '--user=root'
131
self.drizzledump = self.code_tree.drizzledump
132
self.drizzle_client = self.code_tree.drizzle_client
133
self.drizzleimport = self.code_tree.drizzleimport
134
self.drizzleadmin = self.code_tree.drizzleadmin
135
self.drizzleslap = self.code_tree.drizzleslap
136
self.server_path = self.code_tree.drizzle_server
137
self.drizzle_client_path = self.code_tree.drizzle_client
138
self.schemawriter = self.code_tree.schemawriter
140
self.initialize_databases()
141
self.take_db_snapshot()
144
self.logging.debug_class(self)
147
""" We print out some general useful info """
148
report_values = [ 'name'
153
, 'rabbitmq_node_port'
157
self.logging.info("%s master server:" %(self.owner))
158
for key in report_values:
159
value = vars(self)[key]
160
self.logging.info("%s: %s" %(key.upper(), value))
162
def get_start_cmd(self):
163
""" Return the command string that will start up the server
164
as desired / intended
168
server_args = [ self.process_server_options()
169
, "--mysql-protocol.port=%d" %(self.master_port)
170
, "--mysql-protocol.connect-timeout=60"
171
, "--innodb.data-file-path=ibdata1:20M:autoextend"
172
, "--sort-buffer-size=256K"
173
, "--max-heap-table-size=1M"
174
, "--mysql-unix-socket-protocol.path=%s" %(self.socket_file)
175
, "--pid-file=%s" %(self.pid_file)
176
, "--drizzle-protocol.port=%d" %(self.drizzle_tcp_port)
177
, "--default-storage-engine=%s" %(self.default_storage_engine)
178
, "--datadir=%s" %(self.datadir)
179
, "--tmpdir=%s" %(self.tmpdir)
180
, self.secure_file_string
185
server_args.append('--gdb')
186
return self.system_manager.handle_gdb_reqs(self, server_args)
188
return "%s %s %s & " % ( self.cmd_prefix
190
, " ".join(server_args)
194
def get_stop_cmd(self):
195
""" Return the command that will shut us down """
197
return "%s --user=root --port=%d --shutdown " %(self.drizzle_client_path, self.master_port)
200
def get_ping_cmd(self):
201
"""Return the command string that will
202
ping / check if the server is alive
206
return "%s --ping --port=%d --user=root" % (self.drizzle_client_path, self.master_port)
208
def process_server_options(self):
209
"""Consume the list of options we have been passed.
210
Return a string with them joined
214
return " ".join(self.server_options)
216
def initialize_databases(self):
217
""" Call schemawriter to make db.opt files """
221
for database in databases:
222
db_path = os.path.join(self.datadir,'local',database,'db.opt')
223
cmd = "%s %s %s" %(self.schemawriter, database, db_path)
224
self.system_manager.execute_cmd(cmd)
226
def take_db_snapshot(self):
227
""" Take a snapshot of our vardir for quick restores """
229
self.logging.info("Taking clean db snapshot...")
230
if os.path.exists(self.snapshot_path):
231
# We need to remove an existing path as python shutil
232
# doesn't want an existing target
233
self.system_manager.remove_dir(self.snapshot_path)
234
self.system_manager.copy_dir(self.datadir, self.snapshot_path)
236
def restore_snapshot(self):
237
""" Restore from a stored snapshot """
240
self.logging.verbose("Restoring from db snapshot")
241
if not os.path.exists(self.snapshot_path):
242
self.logging.error("Could not find snapshot: %s" %(self.snapshot_path))
243
self.system_manager.remove_dir(self.datadir)
244
self.system_manager.copy_dir(self.snapshot_path, self.datadir)
247
""" Cleanup - just free ports for now..."""
248
self.system_manager.port_manager.free_ports(self.port_block)
250
def set_server_options(self, server_options):
251
""" We update our server_options to the new set """
252
self.server_options = server_options
255
""" Voodoo to reset ourselves """