~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: patrick crews
  • Date: 2011-01-15 21:27:41 UTC
  • mto: (2119.2.1 drizzle)
  • mto: This revision was merged to the branch mainline in revision 2121.
  • Revision ID: gleebix@gmail.com-20110115212741-htz3af0cib4fwdlv
Updated tree so that test-run.pl and test-run.py may live together in peace for a time

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/python
 
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
#
 
7
 
 
8
""" drizzled.py:  code to allow a serverManager
 
9
    to provision and start up a drizzled server object
 
10
    for test execution
 
11
 
 
12
"""
 
13
 
 
14
# imports
 
15
import os
 
16
import time
 
17
 
 
18
class drizzleServer():
 
19
    """ represents a drizzle server, its possessions
 
20
        (datadir, ports, etc), and methods for controlling
 
21
        and querying it
 
22
 
 
23
    """
 
24
 
 
25
    def __init__(self, name, server_manager, server_options
 
26
                , requester, workdir_root):
 
27
        self.skip_keys = [ 'server_manager'
 
28
                         , 'system_manager'
 
29
                         , 'dirset'
 
30
                         , 'preferred_base_port'
 
31
                         , 'no_secure_file_priv'
 
32
                         , 'secure_file_string'
 
33
                         , 'port_block'
 
34
                         ]
 
35
        self.debug = server_manager.debug
 
36
        self.verbose = server_manager.verbose
 
37
        self.initial_run = 1
 
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
 
46
        self.name = name
 
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
 
50
 
 
51
        # Get our ports
 
52
        self.port_block = self.system_manager.port_manager.get_port_block( self.name
 
53
                                                                         , self.preferred_base_port
 
54
                                                                         , 4 )
 
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]
 
59
        
 
60
 
 
61
        # Generate our working directories
 
62
        self.dirset = { self.name : { 'var': {'std_data_ln':( os.path.join(self.code_tree.testdir,'std_data'))
 
63
                                             ,'log':None
 
64
                                             ,'run':None
 
65
                                             ,'tmp':None
 
66
                                             ,'master-data': {'local': { 'test':None
 
67
                                                                       , 'mysql':None
 
68
                                                                       }
 
69
                                                             }
 
70
                                             }  
 
71
                                    } 
 
72
                      }
 
73
        self.workdir = self.system_manager.create_dirset( workdir_root
 
74
                                                        , self.dirset)
 
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')
 
80
 
 
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 = ''
 
90
        else:
 
91
            self.secure_file_string = "--secure-file-priv='%s'" %(self.vardir)
 
92
        self.user_string = '--user=root'
 
93
 
 
94
        # client files
 
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
 
103
 
 
104
        self.initialize_databases()
 
105
        self.take_db_snapshot()
 
106
 
 
107
        if self.debug:
 
108
            self.logging.debug_class(self)
 
109
 
 
110
    def report(self):
 
111
        """ We print out some general useful info """
 
112
        report_values = [ 'name'
 
113
                        , 'master_port'
 
114
                        , 'drizzle_tcp_port'
 
115
                        , 'mc_port'
 
116
                        , 'pbms_port'
 
117
                        , 'vardir'
 
118
                        , 'status'
 
119
                        ]
 
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))
 
124
 
 
125
    def start(self, expect_fail):
 
126
        """ Start the server, using the options in option_list
 
127
            as well as self.standard_options
 
128
            
 
129
            if expect_fail = 1, we know the server shouldn't 
 
130
            start up
 
131
 
 
132
        """
 
133
        if self.verbose:
 
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()
 
137
                                               , self.master_port
 
138
                                               , self.socket_file
 
139
                                               , self.pid_file
 
140
                                               , self.drizzle_tcp_port
 
141
                                               , self.datadir
 
142
                                               , self.tmpdir
 
143
                                               , self.secure_file_string
 
144
                                               , self.user_string 
 
145
                                               , self.error_log
 
146
                                               )
 
147
        if self.debug:
 
148
            self.logging.debug("Starting server with:")
 
149
            self.logging.debug("%s" %(start_cmd))
 
150
        server_retcode = os.system(start_cmd)
 
151
        
 
152
        timer = 0
 
153
        timeout = self.server_start_timeout
 
154
        while not self.ping(quiet= True) and timer != timeout:
 
155
            time.sleep(1)
 
156
            timer= timer + 1
 
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)))
 
160
                retcode = 1
 
161
     
 
162
        if server_retcode == 0:
 
163
            self.status = 1 # we are running
 
164
 
 
165
        if server_retcode != 0 and not expect_fail:
 
166
            self.logging.error("Server startup command: %s failed with error code %d" %( start_cmd
 
167
                                                                                  , server_retcode))
 
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
 
171
 
 
172
    def stop(self):
 
173
        """ Stop the server """
 
174
        if self.verbose:
 
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)
 
177
        if self.debug:
 
178
            self.logging.debug("%s" %(stop_cmd))
 
179
        retcode, output = self.system_manager.execute_cmd(stop_cmd)
 
180
        if retcode:
 
181
            self.logging.error("Problem shutting down server:")
 
182
            self.logging.error("%s : %s" %(retcode, output))
 
183
        else:
 
184
            self.status = 0 # indicate we are shutdown
 
185
           
 
186
 
 
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)
 
190
        if not quiet:
 
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)
 
193
        return retcode == 0
 
194
 
 
195
    def process_server_options(self):
 
196
        """Consume the list of options we have been passed.
 
197
           Return a string with them joined
 
198
 
 
199
        """
 
200
        
 
201
        return " ".join(self.server_options)
 
202
                  
 
203
    def initialize_databases(self):
 
204
        """ Call schemawriter to make db.opt files """
 
205
        databases = [ 'test'
 
206
                    , 'mysql'
 
207
                    ]
 
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)
 
212
 
 
213
    def take_db_snapshot(self):
 
214
        """ Take a snapshot of our vardir for quick restores """
 
215
       
 
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)
 
222
 
 
223
    def restore_snapshot(self):
 
224
        """ Restore from a stored snapshot """
 
225
        
 
226
        if self.verbose:
 
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)
 
232
 
 
233
    def cleanup(self):
 
234
        """ Cleanup - just free ports for now..."""
 
235
        self.system_manager.port_manager.free_ports(self.port_block)
 
236
 
 
237
    def set_server_options(self, server_options):
 
238
        """ We update our server_options to the new set """
 
239
        self.server_options = server_options
 
240
         
 
241
 
 
242
 
 
243
 
 
244