2
# -*- mode: python; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
5
# Copyright (C) 2010 Patrick Crews
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, write to the Free Software
20
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
""" sysbench_test_execution:
23
code related to the execution of sysbench test cases
25
We are provided access to a testManager with
26
sysbench-specific testCases.
37
import lib.test_mgmt.test_execution as test_execution
39
class sysbenchTestExecutor(test_execution.testExecutor):
40
""" sysbench-specific testExecutor
44
def execute_testCase (self):
45
""" Execute a sysbench testCase
48
test_execution.testExecutor.execute_testCase(self)
51
# prepare the server for sysbench
52
self.prepare_sysbench()
55
self.execute_sysbench()
58
self.current_test_status = self.process_sysbench_output()
59
self.set_server_status(self.current_test_status)
60
self.server_manager.reset_servers(self.name)
62
def prepare_sysbench(self):
63
""" Prepare the server for a sysbench run
64
We use subprocess as we can pass os.environ dicts and whatnot
68
sysbench_outfile = os.path.join(self.logdir,'sysbench.out')
69
sysbench_output = open(sysbench_outfile,'w')
70
sysbench_cmd = ' '.join([self.current_testcase.test_command,'prepare'])
71
self.logging.info("Preparing database for sysbench run...")
73
self.logging.debug(sysbench_cmd)
74
sysbench_subproc = subprocess.Popen( sysbench_cmd
77
, env=self.working_environment
78
, stdout = sysbench_output
79
, stderr = subprocess.STDOUT
81
sysbench_subproc.wait()
82
retcode = sysbench_subproc.returncode
84
sysbench_output.close()
85
sysbench_file = open(sysbench_outfile,'r')
86
output = ''.join(sysbench_file.readlines())
89
self.logging.debug("sysbench_retcode: %d" %(retcode))
90
self.logging.debug(output)
92
self.logging.error("sysbench_prepare failed with retcode %d:" %(retcode))
93
self.logging.error(output)
99
def execute_sysbench(self):
100
""" Execute the commandline and return the result.
101
We use subprocess as we can pass os.environ dicts and whatnot
105
testcase_name = self.current_testcase.fullname
106
self.time_manager.start(testcase_name,'test')
107
sysbench_outfile = os.path.join(self.logdir,'sysbench.out')
108
sysbench_output = open(sysbench_outfile,'w')
109
sysbench_cmd = ' '.join([self.current_testcase.test_command, 'run'])
110
self.logging.info("Executing sysbench: %s" %(sysbench_cmd))
112
sysbench_subproc = subprocess.Popen( sysbench_cmd
114
#, cwd=self.system_manager.sysbench_path
115
, env=self.working_environment
116
, stdout = sysbench_output
117
, stderr = subprocess.STDOUT
119
sysbench_subproc.wait()
120
retcode = sysbench_subproc.returncode
121
execution_time = int(self.time_manager.stop(testcase_name)*1000) # millisec
123
sysbench_output.close()
124
sysbench_file = open(sysbench_outfile,'r')
125
output = ''.join(sysbench_file.readlines())
127
self.logging.debug(output)
128
sysbench_file.close()
131
self.logging.debug("sysbench_retcode: %d" %(retcode))
132
self.current_test_retcode = retcode
133
self.current_test_output = output
134
self.current_test_exec_time = execution_time
136
def process_sysbench_output(self):
137
""" sysbench has run, we now check out what we have
138
We also output the data from the run
141
# This slice code taken from drizzle-automation's sysbench handling
142
# Slice up the output report into a matrix and insert into the DB.
144
'tps': re.compile(r".*transactions\:\s+\d+\D*(\d+\.\d+).*")
145
, 'deadlocksps': re.compile(r".*deadlocks\:\s+\d+\D*(\d+\.\d+).*")
146
, 'rwreqps': re.compile(r".*read\/write\s+requests\:\s+\d+\D*(\d+\.\d+).*")
147
, 'min_req_lat_ms': re.compile(r".*min\:\s+(\d*\.\d+)ms.*")
148
, 'max_req_lat_ms': re.compile(r".*max\:\s+(\d*\.\d+)ms.*")
149
, 'avg_req_lat_ms': re.compile(r".*avg\:\s+(\d*\.\d+)ms.*")
150
, '95p_req_lat_ms': re.compile(r".*approx.\s+95\s+percentile\:\s+(\d+\.\d+)ms.*")
153
for line in self.current_test_output.split("\n"):
154
for key in regexes.keys():
155
result= regexes[key].match(line)
157
run[key]= float(result.group(1)) # group(0) is entire match...
158
# we set our test output to the regex'd-up data
159
# we also make it a single string, separated by newlines
160
self.current_test_output = str(run)[1:-1].replace(',','\n').replace("'",'')
162
if self.current_test_retcode == 0:
167
def handle_system_reqs(self):
168
""" We check our test case and see what we need to do
169
system-wise to get ready. This is likely to be
170
mode-dependent and this is just a placeholder
175
self.process_environment_reqs()
176
self.process_symlink_reqs()
177
self.process_master_sh()
180
def process_master_sh(self):
181
""" We do what we need to if we have a master.sh file """
182
if self.current_testcase.master_sh:
183
retcode, output = self.system_manager.execute_cmd("/bin/sh %s" %(self.current_testcase.master_sh))
185
self.logging.info("retcode: %retcode")
186
self.logging.info("%output")
188
def process_environment_reqs(self):
189
""" We generate the ENV vars we need set
190
and then ask systemManager to do so
193
env_reqs = { 'DRIZZLETEST_VARDIR': self.master_server.vardir
194
, 'DRIZZLE_TMP_DIR': self.master_server.tmpdir
195
, 'MASTER_MYSOCK': self.master_server.socket_file
196
, 'MASTER_MYPORT': str(self.master_server.master_port)
197
, 'MC_PORT': str(self.master_server.mc_port)
198
, 'PBMS_PORT': str(self.master_server.pbms_port)
199
, 'RABBITMQ_NODE_PORT': str(self.master_server.rabbitmq_node_port)
200
, 'DRIZZLE_TCP_PORT': str(self.master_server.drizzle_tcp_port)
201
, 'EXE_DRIZZLE': self.master_server.drizzle_client
202
, 'MASTER_SERVER_SLAVE_CONFIG' : self.master_server.slave_config_file
203
, 'DRIZZLE_DUMP': "%s --no-defaults -uroot -p%d" %( self.master_server.drizzledump
204
, self.master_server.master_port)
205
, 'DRIZZLE_SLAP': "%s -uroot -p%d" %( self.master_server.drizzleslap
206
, self.master_server.master_port)
207
, 'DRIZZLE_IMPORT': "%s -uroot -p%d" %( self.master_server.drizzleimport
208
, self.master_server.master_port)
209
, 'DRIZZLE': "%s -uroot -p%d" %( self.master_server.drizzle_client
210
, self.master_server.master_port)
211
, 'DRIZZLE_ADMIN' : "%s -uroot -p%d" %( self.master_server.drizzleadmin
212
, self.master_server.master_port)
213
, 'DRIZZLE_BASEDIR' : self.system_manager.code_tree.basedir
214
, 'DRIZZLE_TRX_READER' : self.system_manager.code_tree.drizzle_trx_reader
218
self.working_environment = self.system_manager.create_working_environment(env_reqs)
221
def process_symlink_reqs(self):
222
""" Create any symlinks we may need """
225
self.system_manager.create_symlinks(needed_symlinks)