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
8
""" drizzled.py: code to allow a serverManager
9
to provision and start up a drizzled server object
18
class drizzleServer():
19
""" represents a drizzle server, its possessions
20
(datadir, ports, etc), and methods for controlling
25
def __init__(self, name, server_manager, server_options
26
, requester, workdir_root):
27
self.skip_keys = [ 'server_manager'
30
, 'preferred_base_port'
31
, 'no_secure_file_priv'
32
, 'secure_file_string'
35
self.debug = server_manager.debug
36
self.verbose = server_manager.verbose
38
self.owner = requester
39
self.server_options = server_options
40
self.server_manager = server_manager
41
self.system_manager = self.server_manager.system_manager
42
self.logging = self.system_manager.logging
43
self.no_secure_file_priv = self.server_manager.no_secure_file_priv
44
self.code_tree = self.system_manager.code_tree
45
self.preferred_base_port = 9306
47
self.status = 0 # stopped, 1 = running
48
self.bad_run = 0 # was the last test a failure? our state is suspect
49
self.server_start_timeout = 60
52
self.port_block = self.system_manager.port_manager.get_port_block( self.name
53
, self.preferred_base_port
55
self.master_port = self.port_block[0]
56
self.drizzle_tcp_port = self.port_block[1]
57
self.mc_port = self.port_block[2]
58
self.pbms_port = self.port_block[3]
61
# Generate our working directories
62
self.dirset = { self.name : { 'var': {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
66
,'master-data': {'local': { 'test':None
73
self.workdir = self.system_manager.create_dirset( workdir_root
75
self.vardir = os.path.join(self.workdir,'var')
76
self.tmpdir = os.path.join(self.vardir,'tmp')
77
self.rundir = os.path.join(self.vardir,'run')
78
self.logdir = os.path.join(self.vardir,'log')
79
self.datadir = os.path.join(self.vardir,'master-data')
81
self.error_log = os.path.join(self.logdir,('%s.err' %(self.name)))
82
self.pid_file = os.path.join(self.rundir,('%s.pid' %(self.name)))
83
self.socket_file = os.path.join(self.vardir, ('%s.sock' %(self.name)))
84
self.timer_file = os.path.join(self.logdir,('timer'))
85
self.snapshot_path = os.path.join(self.tmpdir,('snapshot_%s' %(self.master_port)))
86
# We want to use --secure-file-priv = $vardir by default
87
# but there are times / tools when we need to shut this off
88
if self.no_secure_file_priv:
89
self.secure_file_string = ''
91
self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
92
self.user_string = '--user=root'
95
self.drizzledump = self.code_tree.drizzledump
96
self.drizzle_client = self.code_tree.drizzle_client
97
self.drizzleimport = self.code_tree.drizzleimport
98
self.drizzleadmin = self.code_tree.drizzleadmin
99
self.drizzleslap = self.code_tree.drizzleslap
100
self.server_path = self.code_tree.drizzle_server
101
self.drizzle_client_path = self.code_tree.drizzle_client
102
self.schemawriter = self.code_tree.schemawriter
104
self.initialize_databases()
105
self.take_db_snapshot()
108
self.logging.debug_class(self)
111
""" We print out some general useful info """
112
report_values = [ 'name'
120
self.logging.info("%s master server:" %(self.owner))
121
for key in report_values:
122
value = vars(self)[key]
123
self.logging.info("%s: %s" %(key.upper(), value))
125
def start(self, expect_fail):
126
""" Start the server, using the options in option_list
127
as well as self.standard_options
129
if expect_fail = 1, we know the server shouldn't
134
self.logging.verbose("Starting server: %s.%s" %(self.owner, self.name))
135
start_cmd = "%s %s --mysql-protocol.port=%d --mysql-protocol.connect-timeout=60 --mysql-unix-socket-protocol.path=%s --pid-file=%s --drizzle-protocol.port=%d --datadir=%s --tmpdir=%s --innodb.data-file-path=ibdata1:20M:autoextend %s %s > %s 2>&1 & " % ( self.server_path
136
, self.process_server_options()
140
, self.drizzle_tcp_port
143
, self.secure_file_string
148
self.logging.debug("Starting server with:")
149
self.logging.debug("%s" %(start_cmd))
150
server_retcode = os.system(start_cmd)
153
timeout = self.server_start_timeout
154
while not self.ping(quiet= True) and timer != timeout:
157
# We make sure the server is running and return False if not
158
if timer == timeout and not self.ping(quiet= True):
159
self.logging.error(( "Server failed to start within %d seconds. This could be a problem with the test machine or the server itself" %(timeout)))
162
if server_retcode == 0:
163
self.status = 1 # we are running
165
if server_retcode != 0 and not expect_fail:
166
self.logging.error("Server startup command: %s failed with error code %d" %( start_cmd
168
elif server_retcode == 0 and expect_fail:
169
self.logging.error("Server startup command :%s expected to fail, but succeeded" %(start_cmd))
170
return server_retcode and expect_fail
173
""" Stop the server """
175
self.logging.verbose("Stopping server %s.%s" %(self.owner, self.name))
176
stop_cmd = "%s --user=root --port=%d --shutdown " %(self.drizzle_client_path, self.master_port)
178
self.logging.debug("%s" %(stop_cmd))
179
retcode, output = self.system_manager.execute_cmd(stop_cmd)
181
self.logging.error("Problem shutting down server:")
182
self.logging.error("%s : %s" %(retcode, output))
184
self.status = 0 # indicate we are shutdown
187
def ping(self, quiet= False):
188
"""Pings the server. Returns True if server is up and running, False otherwise."""
189
ping_cmd= "%s --ping --port=%d" % (self.drizzle_client_path, self.master_port)
191
self.logging.info("Pinging Drizzled server on port %d" % self.master_port)
192
(retcode, output)= self.system_manager.execute_cmd(ping_cmd, must_pass = 0)
195
def process_server_options(self):
196
"""Consume the list of options we have been passed.
197
Return a string with them joined
201
return " ".join(self.server_options)
203
def initialize_databases(self):
204
""" Call schemawriter to make db.opt files """
208
for database in databases:
209
db_path = os.path.join(self.datadir,'local',database,'db.opt')
210
cmd = "%s %s %s" %(self.schemawriter, database, db_path)
211
self.system_manager.execute_cmd(cmd)
213
def take_db_snapshot(self):
214
""" Take a snapshot of our vardir for quick restores """
216
self.logging.info("Taking clean db snapshot...")
217
if os.path.exists(self.snapshot_path):
218
# We need to remove an existing path as python shutil
219
# doesn't want an existing target
220
self.system_manager.remove_dir(self.snapshot_path)
221
self.system_manager.copy_dir(self.datadir, self.snapshot_path)
223
def restore_snapshot(self):
224
""" Restore from a stored snapshot """
227
self.logging.verbose("Restoring from db snapshot")
228
if not os.path.exists(self.snapshot_path):
229
self.logging.error("Could not find snapshot: %s" %(self.snapshot_path))
230
self.system_manager.remove_dir(self.datadir)
231
self.system_manager.copy_dir(self.snapshot_path, self.datadir)
234
""" Cleanup - just free ports for now..."""
235
self.system_manager.port_manager.free_ports(self.port_block)
237
def set_server_options(self, server_options):
238
""" We update our server_options to the new set """
239
self.server_options = server_options