~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to tests/lib/server_mgmt/mysqld.py

  • Committer: Mark Atwood
  • Date: 2011-10-11 22:37:47 UTC
  • mfrom: (2429.2.1 dbqp_revamp)
  • Revision ID: me@mark.atwood.name-20111011223747-vomebzgvnxxysqrm
mergeĀ lp:~patrick-crews/drizzle/dbqp_revamp

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
# -*- mode: python; indent-tabs-mode: nil; -*-
 
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
4
#
 
5
# Copyright (C) 2010,2011 Patrick Crews
 
6
#
 
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.
 
11
#
 
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.
 
16
#
 
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
 
20
 
 
21
 
 
22
""" mysqld.py:  code to allow a serverManager
 
23
    to provision and start up a mysqld server object
 
24
    for test execution
 
25
 
 
26
"""
 
27
 
 
28
# imports
 
29
import os
 
30
import sys
 
31
import subproc
 
32
 
 
33
 
 
34
from lib.server_mgmt.server import Server
 
35
 
 
36
class mysqlServer(Server):
 
37
    """ represents a mysql server, its possessions
 
38
        (datadir, ports, etc), and methods for controlling
 
39
        and querying it
 
40
 
 
41
        TODO: create a base server class that contains
 
42
              standard methods from which we can inherit
 
43
              Currently there are definitely methods / attr
 
44
              which are general
 
45
 
 
46
    """
 
47
 
 
48
    def __init__( self, name, server_manager, code_tree, default_storage_engine
 
49
                , server_options, requester, workdir_root):
 
50
        super(mysqlServer, self).__init__( name
 
51
                                           , server_manager
 
52
                                           , code_tree
 
53
                                           , default_storage_engine
 
54
                                           , server_options
 
55
                                           , requester
 
56
                                           , workdir_root)
 
57
        self.preferred_base_port = 9306
 
58
        
 
59
        # client files
 
60
        self.mysqldump = self.code_tree.mysqldump
 
61
        self.mysqladmin = self.code_tree.mysqladmin
 
62
        self.mysql_client = self.code_tree.mysql_client
 
63
        self.mysqlimport = self.code_tree.mysqlimport
 
64
        self.mysqlslap = self.code_tree.mysqlslap
 
65
        self.server_path = self.code_tree.mysql_server
 
66
        self.mysql_client_path = self.code_tree.mysql_client
 
67
      
 
68
        # important stuff
 
69
        self.langdir = self.code_tree.langdir
 
70
        self.charsetdir = self.code_tree.charsetdir
 
71
        self.bootstrap_file = self.code_tree.bootstrap_path
 
72
        self.bootstrap_cmd = None
 
73
 
 
74
        # Get our ports
 
75
        self.port_block = self.system_manager.port_manager.get_port_block( self.name
 
76
                                                                         , self.preferred_base_port
 
77
                                                                         , 1 )
 
78
        self.master_port = self.port_block[0]
 
79
 
 
80
        # Generate our working directories
 
81
        self.dirset = { self.name : { 'var': {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
 
82
                                             ,'log':None
 
83
                                             ,'run':None
 
84
                                             ,'tmp':None
 
85
                                             ,'master-data': {'local': { 'test':None
 
86
                                                                       , 'mysql':None
 
87
                                                                       }
 
88
                                                             }
 
89
                                             }  
 
90
                                    } 
 
91
                      }
 
92
        self.workdir = self.system_manager.create_dirset( workdir_root
 
93
                                                        , self.dirset)
 
94
        self.vardir = os.path.join(self.workdir,'var')
 
95
        self.tmpdir = os.path.join(self.vardir,'tmp')
 
96
        self.rundir = os.path.join(self.vardir,'run')
 
97
        self.logdir = os.path.join(self.vardir,'log')
 
98
        self.datadir = os.path.join(self.vardir,'master-data')
 
99
 
 
100
        self.error_log = os.path.join(self.logdir,('%s.err' %(self.name)))
 
101
        self.bootstrap_log = os.path.join(self.logdir,('bootstrap.log'))
 
102
        self.pid_file = os.path.join(self.rundir,('%s.pid' %(self.name)))
 
103
        self.socket_file = os.path.join(self.vardir, ('%s.sock' %(self.name)))
 
104
        self.timer_file = os.path.join(self.logdir,('timer'))
 
105
 
 
106
        self.snapshot_path = os.path.join(self.tmpdir,('snapshot_%s' %(self.master_port)))
 
107
        # We want to use --secure-file-priv = $vardir by default
 
108
        # but there are times / tools when we need to shut this off
 
109
        if self.no_secure_file_priv:
 
110
            self.secure_file_string = ''
 
111
        else:
 
112
            self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
 
113
        self.user_string = '--user=root'
 
114
 
 
115
        self.initialize_databases()
 
116
        self.take_db_snapshot()
 
117
 
 
118
        self.logging.debug_class(self)
 
119
 
 
120
    def report(self):
 
121
        """ We print out some general useful info """
 
122
        report_values = [ 'name'
 
123
                        , 'master_port'
 
124
                        , 'mysql_tcp_port'
 
125
                        , 'vardir'
 
126
                        , 'status'
 
127
                        ]
 
128
        self.logging.info("%s server:" %(self.owner))
 
129
        for key in report_values:
 
130
          value = vars(self)[key] 
 
131
          self.logging.info("%s: %s" %(key.upper(), value))
 
132
 
 
133
    def initialize_databases(self):
 
134
        """ Do the voodoo required to have a working database setup.
 
135
            For MySQL, this is calling the server with the 
 
136
            --bootstrap argument.  We generate the bootstrap
 
137
            file during codeTree intialization as the file is standard for
 
138
            all MySQL servers that are spawned from a single codeTree
 
139
 
 
140
        """
 
141
 
 
142
        # generate the bootstrap startup command
 
143
        if not self.bootstrap_cmd:
 
144
            mysqld_args = [ "--no-defaults"
 
145
                          , "--bootstrap"
 
146
                          , "--basedir=%s" %(self.code_tree.basedir)
 
147
                          , "--datadir=%s" %(self.datadir)
 
148
                          , "--loose-skip-falcon"
 
149
                          , "--loose-skip-ndbcluster"
 
150
                          , "--tmpdir=%s" %(self.tmpdir)
 
151
                          , "--core-file"
 
152
                          , "--lc-messages-dir=%s" %(self.langdir)
 
153
                          , "--character-sets-dir=%s" %(self.charsetdir)
 
154
                          ]
 
155
            # We add server_path into the mix this way as we
 
156
            # may alter how we store / handle server args later
 
157
            mysqld_args = [self.server_path].append(mysqld_args)
 
158
            self.bootstrap_cmd = " ".join(mysqld_args)
 
159
        # execute our command
 
160
        bootstrap_subproc = subprocess.Popen( self.bootstrap_cmd
 
161
                                            , shell=True
 
162
                                            , stdout=self.bootstrap_log
 
163
                                            , stderr=self.bootstrap_log
 
164
                                            )
 
165
        bootstrap_subproc.wait()
 
166
        bootstrap_retcode = bootstrap_subproc.returncode
 
167
        if bootstrap_retcode:
 
168
            self.logging.error("Received retcode: %s executing command: %s"
 
169
                               %(bootstrap_retcode, self.bootstrap_cmd))
 
170
            self.logging.error("Check the bootstrap log: %s" %(self.bootstrap_log))
 
171
            sys.exit(1)
 
172
 
 
173
 
 
174
    def get_start_cmd(self):
 
175
        """ Return the command string that will start up the server 
 
176
            as desired / intended
 
177
 
 
178
        """
 
179
 
 
180
        server_args = [ self.process_server_options()
 
181
                      , "--mysql-protocol.port=%d" %(self.master_port)
 
182
                      , "--mysql-protocol.connect-timeout=60"
 
183
                      , "--innodb.data-file-path=ibdata1:20M:autoextend"
 
184
                      , "--sort-buffer-size=256K"
 
185
                      , "--max-heap-table-size=1M"
 
186
                      , "--mysql-unix-socket-protocol.path=%s" %(self.socket_file)
 
187
                      , "--pid-file=%s" %(self.pid_file)
 
188
                      , "--mysql-protocol.port=%d" %(self.mysql_tcp_port)
 
189
                      , "--default-storage-engine=%s" %(self.default_storage_engine)
 
190
                      , "--datadir=%s" %(self.datadir)
 
191
                      , "--tmpdir=%s" %(self.tmpdir)
 
192
                      , self.secure_file_string
 
193
                      , self.user_string
 
194
                      ]
 
195
 
 
196
        if self.gdb:
 
197
            server_args.append('--gdb')
 
198
            return self.system_manager.handle_gdb_reqs(self, server_args)
 
199
        else:
 
200
            return "%s %s %s & " % ( self.cmd_prefix
 
201
                                   , self.server_path
 
202
                                   , " ".join(server_args)
 
203
                                   )
 
204
 
 
205
 
 
206
    def get_stop_cmd(self):
 
207
        """ Return the command that will shut us down """
 
208
        
 
209
        return "%s --user=root --port=%d --connect-timeout=5 --silent --password= --shutdown " %(self.mysql_client_path, self.master_port)
 
210
           
 
211
 
 
212
    def get_ping_cmd(self):
 
213
        """Return the command string that will 
 
214
           ping / check if the server is alive 
 
215
 
 
216
        """
 
217
 
 
218
        return "%s --ping --port=%d --user=root" % (self.mysql_client_path, self.master_port)
 
219
 
 
220
    def is_started(self):
 
221
        """ Determine if the server is up and running - 
 
222
            this may vary from server type to server type
 
223
 
 
224
        """
 
225
 
 
226
        # We experiment with waiting for a pid file to be created vs. pinging
 
227
        # This is what test-run.pl does and it helps us pass logging_stats tests
 
228
        # while not self.ping_server(server, quiet=True) and timer != timeout:
 
229
 
 
230
        return self.system_manager.find_path( [self.pid_file]
 
231
                                            , required=0)
 
232
 
 
233