~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-08 04:50:51 UTC
  • mfrom: (2430.1.1 rf)
  • Revision ID: me@mark.atwood.name-20111008045051-6ha1qiy7k2a9c3jv
Tags: 2011.10.27
mergeĀ lp:~olafvdspek/drizzle/refactor2

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