~drizzle-trunk/drizzle/development

2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
1
#! /usr/bin/env python
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
2
# -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
3
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
#
5
# Copyright (C) 2010 Patrick Crews
6
#
2121.3.2 by patrick crews
Updated license verbiage
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
2121.3.1 by patrick crews
Added licensing text to dbqp files
20
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
21
22
""" drizzled.py:  code to allow a serverManager
23
    to provision and start up a drizzled server object
24
    for test execution
25
26
"""
27
28
# imports
29
import os
30
31
class drizzleServer():
32
    """ represents a drizzle server, its possessions
33
        (datadir, ports, etc), and methods for controlling
34
        and querying it
35
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
36
        TODO: create a base server class that contains
37
              standard methods from which we can inherit
38
              Currently there are definitely methods / attr
39
              which are general
40
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
41
    """
42
43
    def __init__(self, name, server_manager, server_options
44
                , requester, workdir_root):
45
        self.skip_keys = [ 'server_manager'
46
                         , 'system_manager'
47
                         , 'dirset'
48
                         , 'preferred_base_port'
49
                         , 'no_secure_file_priv'
50
                         , 'secure_file_string'
51
                         , 'port_block'
52
                         ]
53
        self.debug = server_manager.debug
54
        self.verbose = server_manager.verbose
55
        self.initial_run = 1
56
        self.owner = requester
57
        self.server_options = server_options
58
        self.server_manager = server_manager
2088.9.20 by patrick crews
Minor tweak to time reporting + changes to catch rogue servers prior to shutdown
59
        # We register with server_manager asap
60
        self.server_manager.log_server(self, requester)
61
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
62
        self.system_manager = self.server_manager.system_manager
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
63
        self.valgrind = self.system_manager.valgrind
64
        if self.valgrind:
65
            self.valgrind_time_buffer = 10
66
        else:
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
67
            self.valgrind_time_buffer = 1
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
68
        self.cmd_prefix = self.system_manager.cmd_prefix
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
69
        self.logging = self.system_manager.logging
70
        self.no_secure_file_priv = self.server_manager.no_secure_file_priv
71
        self.code_tree = self.system_manager.code_tree
72
        self.preferred_base_port = 9306
73
        self.name = name
74
        self.status = 0 # stopped, 1 = running
2088.9.20 by patrick crews
Minor tweak to time reporting + changes to catch rogue servers prior to shutdown
75
        self.tried_start = 0
2088.9.4 by patrick crews
Updates to server management and signalling a bad server start
76
        self.failed_test = 0 # was the last test a failure?  our state is suspect
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
77
        self.server_start_timeout = 60 * self.valgrind_time_buffer
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
78
79
        # Get our ports
80
        self.port_block = self.system_manager.port_manager.get_port_block( self.name
81
                                                                         , self.preferred_base_port
2088.9.23 by patrick crews
Added initial options for controlling valgrind / gdb. Also added allocation of RABBIT_MQ_NODE_PORT for drizzled servers (we need this for tests)
82
                                                                         , 5 )
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
83
        self.master_port = self.port_block[0]
84
        self.drizzle_tcp_port = self.port_block[1]
85
        self.mc_port = self.port_block[2]
86
        self.pbms_port = self.port_block[3]
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
87
        self.rabbitmq_node_port = self.port_block[4]
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
88
        
89
90
        # Generate our working directories
91
        self.dirset = { self.name : { 'var': {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
92
                                             ,'log':None
93
                                             ,'run':None
94
                                             ,'tmp':None
95
                                             ,'master-data': {'local': { 'test':None
96
                                                                       , 'mysql':None
97
                                                                       }
98
                                                             }
99
                                             }  
100
                                    } 
101
                      }
102
        self.workdir = self.system_manager.create_dirset( workdir_root
103
                                                        , self.dirset)
104
        self.vardir = os.path.join(self.workdir,'var')
105
        self.tmpdir = os.path.join(self.vardir,'tmp')
106
        self.rundir = os.path.join(self.vardir,'run')
107
        self.logdir = os.path.join(self.vardir,'log')
108
        self.datadir = os.path.join(self.vardir,'master-data')
109
110
        self.error_log = os.path.join(self.logdir,('%s.err' %(self.name)))
111
        self.pid_file = os.path.join(self.rundir,('%s.pid' %(self.name)))
112
        self.socket_file = os.path.join(self.vardir, ('%s.sock' %(self.name)))
113
        self.timer_file = os.path.join(self.logdir,('timer'))
114
        self.snapshot_path = os.path.join(self.tmpdir,('snapshot_%s' %(self.master_port)))
115
        # We want to use --secure-file-priv = $vardir by default
116
        # but there are times / tools when we need to shut this off
117
        if self.no_secure_file_priv:
118
            self.secure_file_string = ''
119
        else:
120
            self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
121
        self.user_string = '--user=root'
122
123
        # client files
124
        self.drizzledump = self.code_tree.drizzledump
125
        self.drizzle_client = self.code_tree.drizzle_client
126
        self.drizzleimport = self.code_tree.drizzleimport
127
        self.drizzleadmin = self.code_tree.drizzleadmin
128
        self.drizzleslap = self.code_tree.drizzleslap
129
        self.server_path = self.code_tree.drizzle_server
130
        self.drizzle_client_path = self.code_tree.drizzle_client
131
        self.schemawriter = self.code_tree.schemawriter
132
133
        self.initialize_databases()
134
        self.take_db_snapshot()
135
136
        if self.debug:
137
            self.logging.debug_class(self)
138
139
    def report(self):
140
        """ We print out some general useful info """
141
        report_values = [ 'name'
142
                        , 'master_port'
143
                        , 'drizzle_tcp_port'
144
                        , 'mc_port'
145
                        , 'pbms_port'
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
146
                        , 'rabbitmq_node_port'
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
147
                        , 'vardir'
148
                        , 'status'
149
                        ]
150
        self.logging.info("%s master server:" %(self.owner))
151
        for key in report_values:
152
          value = vars(self)[key] 
153
          self.logging.info("%s: %s" %(key.upper(), value))
154
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
155
    def get_start_cmd(self):
156
        """ Return the command string that will start up the server 
157
            as desired / intended
158
 
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
159
        """
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
160
      
161
        return "%s %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 --sort-buffer-size=256K --max-heap-table-size=1M %s %s > %s 2>&1 & " % ( self.cmd_prefix
2088.9.24 by patrick crews
Added code to handle valgrind. Currently not working - getting bad error on malloc-fill=DEADBEEF : (, checking in anyway as it is largely there
162
                                               , self.server_path
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
163
                                               , self.process_server_options()
164
                                               , self.master_port
165
                                               , self.socket_file
166
                                               , self.pid_file
167
                                               , self.drizzle_tcp_port
168
                                               , self.datadir
169
                                               , self.tmpdir
170
                                               , self.secure_file_string
171
                                               , self.user_string 
172
                                               , self.error_log
173
                                               )
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
174
175
    def get_stop_cmd(self):
176
        """ Return the command that will shut us down """
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
177
        
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
178
        return "%s --user=root --port=%d --shutdown " %(self.drizzle_client_path, self.master_port)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
179
           
180
2144.1.1 by patrick crews
Overhaul of code. We can run rabbitmq : ) We now better encapsulate a per-executor working environment = one step closer to --parallel >: ) using subprocess goodness for server control
181
    def get_ping_cmd(self):
182
        """Return the command string that will 
183
           ping / check if the server is alive 
184
185
        """
186
187
        return "%s --ping --port=%d --user=root" % (self.drizzle_client_path, self.master_port)
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
188
189
    def process_server_options(self):
190
        """Consume the list of options we have been passed.
191
           Return a string with them joined
192
193
        """
194
        
195
        return " ".join(self.server_options)
196
                  
197
    def initialize_databases(self):
198
        """ Call schemawriter to make db.opt files """
199
        databases = [ 'test'
200
                    , 'mysql'
201
                    ]
202
        for database in databases:
203
            db_path = os.path.join(self.datadir,'local',database,'db.opt')
204
            cmd = "%s %s %s" %(self.schemawriter, database, db_path)
205
            self.system_manager.execute_cmd(cmd)
206
207
    def take_db_snapshot(self):
208
        """ Take a snapshot of our vardir for quick restores """
209
       
210
        self.logging.info("Taking clean db snapshot...")
211
        if os.path.exists(self.snapshot_path):
212
            # We need to remove an existing path as python shutil
213
            # doesn't want an existing target
214
            self.system_manager.remove_dir(self.snapshot_path)
215
        self.system_manager.copy_dir(self.datadir, self.snapshot_path)
216
217
    def restore_snapshot(self):
218
        """ Restore from a stored snapshot """
219
        
220
        if self.verbose:
221
            self.logging.verbose("Restoring from db snapshot")
222
        if not os.path.exists(self.snapshot_path):
223
            self.logging.error("Could not find snapshot: %s" %(self.snapshot_path))
224
        self.system_manager.remove_dir(self.datadir)
225
        self.system_manager.copy_dir(self.snapshot_path, self.datadir)
226
227
    def cleanup(self):
228
        """ Cleanup - just free ports for now..."""
229
        self.system_manager.port_manager.free_ports(self.port_block)
230
231
    def set_server_options(self, server_options):
232
        """ We update our server_options to the new set """
233
        self.server_options = server_options
2088.9.4 by patrick crews
Updates to server management and signalling a bad server start
234
235
    def reset(self):
236
        """ Voodoo to reset ourselves """
237
        self.failed_test = 0
2088.9.1 by patrick crews
Updated tree so that test-run.pl and test-run.py may live together in peace for a time
238
         
239
240
241
242