~sahil-cooner/drizzle-automation/neuro_damages_killer_mail_code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#! /usr/bin/python
# -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
# vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
#
# Copyright (C) 2009 Sun Microsystems
#
# Authors:
#
#  Jay Pipes <joinfu@sun.com>
#
# This file is part of the Drizzle Automation Project.
#
# The Drizzle Automation Project is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation.
#
# The Drizzle Automation Project is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with The Drizzle Automation Project (see COPYING.LESSER). If not, 
# see <http://www.gnu.org/licenses/>.

"""The main automation script runner

The automation suite is a set of commands designed to ease the processing
of regression tests, code coverage tests, and benchmarking for Drizzle.

The drizzle-automation script is called with a command and some options.
The main runner script calls a command-specific runner to do its work.

There are currently two distinct code paths used by the automation runner, 
and they determine how a server is built, whether a source control system
is used to pull a revision/version of the server, and what controls the 
server:

  * Run a command against a server built from source in an "Automation Sandbox"

  This code path is used when the automation suite is processing a command
  on a branch of code contained in a BZR branch.  In order to facilitate 
  processing and saving results on a series of BZR revisions for a specific
  branch, the runner creates a Sandbox object.  The Sandbox uses BZR to 
  create a specific branch to run the automation command at a specified revision.

  For instance, assume a main BZR branch called "trunk", located at ~/repos/drizzle/trunk.

  If we wanted to run the "sysbench" command against this branch for revisions
  r930 through r932, we could call the drizzle-automation script like so:

  $> drizzle-automation --sysbench-config=some_benchmark_config --bzr-branch=trunk --r930..932 sysbench

  This would create 3 sandboxes:

    ~/repos/drizzle/trunk-sysbench-r930
    ~/repos/drizzle/trunk-sysbench-r931
    ~/repos/drizzle/trunk-sysbench-r932

  Each containing a version of the trunk BZR branch at a specific revision.  The sysbench command
  would be run in each sandbox, and each run would not build a server in a directory which 
  might be affected by another run.

  This is the default way of processing a command.  If any of the --bzr-xxxx options are 
  provided to the runner, it will use BZR and the automation sandbox to do its work.

  * Run a command against a pre-built server using MySQL Sandbox

  This code path is used when running an automation command against a *non-BZR*
  server.  This is necessary for testing or benchmarking pre-built binaries or servers
  installed in something like MySQL Sandbox, and no BZR commands are relevant to the
  automation run.

  When the --mysql-sandbox-xxxx options are provided to the automation runner, the
  runner will not build a server from source or create an automation sandbox.  Instead,
  it will perform the command using MySQL Sandbox to start, stop, and control the server.
"""

# Note that much of this originally was a shell script, and so it's
# not particularly "Pythonic".  Much help is needed to get the code
# more structured and pretty!

import sys
import os
import logging

try:
  import lib
except ImportError, e:
  sys.stderr.write("ERROR: Couldn't import automation library. Please check the directory containing the automation library is on your PYTHONPATH.\n")
  sys.exit(1)

import lib.options
import lib.config
import lib.util

# Container for all our configuration and option arguments. 
variables= {}

# Process our command first
variables['command']= lib.options.command.lower()

# Merge in our configuration file variables
variables= lib.config.process_config(variables)

# Figure out which mode we'll be operating in...
processing_mode= lib.options.options.getProcessingMode()

# Merge/override with CLI options
variables= lib.options.options.processOptions(variables)

# Setup our logging facilities
if variables['log_file'] == 'stdout':
  logging.basicConfig(stream= sys.stdout, level= logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s')
else:
  logging.basicConfig(filename= variables['log_file'], level= logging.DEBUG, format='%(asctime)s %(levelname)s: %(message)s')

# In dry-run mode, print a list of the configuration variables found
# @TODO Make this nicer and more robust...
if variables['dry_run']:
  lib.util.pretty_print_configuration(variables)
  sys.exit(0)

# Here, we set the runner script based on the 
# command specified...

command= variables['command'] # lib/options.py ensures we have a command specified...

if command == 'sloc':
  import sloc.run as runner
elif command == 'lcov':
  import lcov.run as runner
elif command == 'sysbench':
  import sysbench.run as runner
elif command in ('doxy','doxygen'):
  import doxygen.run as runner
elif command == 'valgrind':
  import valgrind.run as runner

import lib.db
lib.db.init(variables)    # Checks dependencies and required configuration variables for the DB...

# OK, so we've parsed our basic configuration variables and options
# at this point.  Now, we need to figure out what code path we need
# to take.  When operating on a BZR branch, we use an automation 
# sandbox and supply the command runner with the root directory of the
# automation sandbox.

if processing_mode == "bzr":

  # If we're here, we are guaranteed to have all our required 
  # configuration variables, so localize the required ones to
  # make calling subroutines a little cleaner...
  repo_dir= variables['bzr_repo_dir']
  branch= variables['bzr_branch']
  revision= variables['bzr_revision']
  revision_step= variables['bzr_revision_step']

  # We now set up our sandbox for the run.  The sandbox always requires
  # the following information, supplied either as CLI options or pulled
  # from configuration files:
  #  * repository directory         (--repo-dir)    or [defaults][repo-dir]
  #  * command
  #  * branch nickname              (--branch)      or [defaults][branch]
  #  * revision we wish to process  (--revision)
  #
  # Since a range of revisions may be specified, we want to establish one
  # sandbox per tuple of the above elements.  The sandbox is really just
  # a directory containing a bzr branch from the parent --branch-dir where
  # the automation process can do its work in isolation from other runs

  import lib.sandbox
  import lib.bzrbranch
  revision_range= lib.bzrbranch.get_revision_range(repo_dir, branch, revision, revision_step)

  # OK, so for each revision create an automation sandbox and execute our runner
  for revision in revision_range:
    sandbox= lib.sandbox.Sandbox(command, repo_dir, branch, revision)
    sandbox.create()

    variables['working_dir']= sandbox.get_working_dir()
    variables['bzr_revision']= revision

    result= runner.execute(processing_mode, variables)
    if not result:
      if variables['force'] is True:
        pass
      else:
        logging.error("Failed to execute runner in sandbox: \"%s\". Exiting." % branch_dir)
        sys.exit(1)

else:

  # This code path is run when we are processing commands against pre-built
  # binaries or servers not in a BZR branch.

  variables['working_dir']= os.path.join(repo_dir, branch)
  results= runner.execute(processing_mode, variables)
  if not results:
    logging.error("Failed to execute runner in: \"%s\". Exiting." % branch_dir)
    sys.exit(1)