Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin / __init__.py @ 79a5c431

History | View | Annotate | Download (9.1 kB)

1
# Copyright 2013 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
"""
35
Burnin: functional tests for Synnefo
36

37
"""
38

    
39
import sys
40
import optparse
41

    
42
from synnefo_tools import version
43
from synnefo_tools.burnin import common
44
from synnefo_tools.burnin.astakos_tests import AstakosTestSuite
45
from synnefo_tools.burnin.cyclades_tests import FlavorsTestSuite
46
from synnefo_tools.burnin.pithos_tests import PithosTestSuite
47

    
48

    
49
# --------------------------------------------------------------------
50
# Define our TestSuites
51
TESTSUITES = [
52
    AstakosTestSuite,
53
    FlavorsTestSuite,
54
    PithosTestSuite,
55
    ]
56

    
57
TSUITES_NAMES = [tsuite.__name__ for tsuite in TESTSUITES]
58

    
59

    
60
def string_to_class(names):
61
    """Convert class namesto class objects"""
62
    return [eval(name) for name in names]
63

    
64

    
65
# --------------------------------------------------------------------
66
# Parse arguments
67
def parse_comma(option, _, value, parser):
68
    """Parse comma separated arguments"""
69
    tests = set(TSUITES_NAMES)
70
    parse_input = value.split(',')
71

    
72
    if not (set(parse_input)).issubset(tests):
73
        raise optparse.OptionValueError("The selected set of tests is invalid")
74

    
75
    setattr(parser.values, option.dest, value.split(','))
76

    
77

    
78
def parse_arguments(args):
79
    """Parse burnin arguments"""
80
    kwargs = {}
81
    kwargs["usage"] = "%prog [options]"
82
    kwargs["description"] = \
83
        "%prog runs a number of test scenarios on a Synnefo deployment."
84

    
85
    # Used * or ** magic. pylint: disable-msg=W0142
86
    parser = optparse.OptionParser(**kwargs)
87
    parser.disable_interspersed_args()
88

    
89
    parser.add_option(
90
        "--auth-url", action="store",
91
        type="string", default=None, dest="auth_url",
92
        help="The AUTH URI to use to reach the Synnefo API")
93
    parser.add_option(
94
        "--token", action="store",
95
        type="string", default=None, dest="token",
96
        help="The token to use for authentication to the API")
97
    parser.add_option(
98
        "--failfast", action="store_true",
99
        default=False, dest="failfast",
100
        help="Fail immediately if one of the tests fails")
101
    parser.add_option(
102
        "--no-ipv6", action="store_false",
103
        default=True, dest="use_ipv6",
104
        help="Disable IPv6 related tests")
105
    parser.add_option(
106
        "--action-timeout", action="store",
107
        type="int", default=300, dest="action_timeout", metavar="TIMEOUT",
108
        help="Wait TIMEOUT seconds for a server action to complete, "
109
             "then the test is considered failed")
110
    parser.add_option(
111
        "--action-warning", action="store",
112
        type="int", default=120, dest="action_warning", metavar="TIMEOUT",
113
        help="Warn if TIMEOUT seconds have passed and a server action "
114
             "has not been completed yet")
115
    parser.add_option(
116
        "--query-interval", action="store",
117
        type="int", default=3, dest="query_interval", metavar="INTERVAL",
118
        help="Query server status when requests are pending "
119
             "every INTERVAL seconds")
120
    parser.add_option(
121
        "--force-flavor", action="store",
122
        type="string", default=None, dest="force_flavor", metavar="FLAVOR",
123
        help="Force all server creations to use the specified FLAVOR "
124
             "instead of a randomly chosen one. Supports both search by name "
125
             "(reg expression) with \"name:flavor name\" or by id with "
126
             "\"id:flavor id\"")
127
    parser.add_option(
128
        "--force-image", action="store",
129
        type="string", default=None, dest="force_image", metavar="IMAGE",
130
        help="Force all server creations to use the specified IMAGE "
131
             "instead of the default one (a Debian Base image). Just like the "
132
             "--force-flavor option, it supports both search by name and id")
133
    parser.add_option(
134
        "--show-stale", action="store_true",
135
        default=False, dest="show_stale",
136
        help="Show stale servers from previous runs. A server is considered "
137
             "stale if its name starts with `%s'. If stale servers are found, "
138
             "exit with exit status 1." % common.SNF_TEST_PREFIX)
139
    parser.add_option(
140
        "--delete-stale", action="store_true",
141
        default=False, dest="delete_stale",
142
        help="Delete stale servers from previous runs")
143
    parser.add_option(
144
        "--log-folder", action="store",
145
        type="string", default="/var/log/burnin/", dest="log_folder",
146
        help="Define the absolute path where the output log is stored")
147
    parser.add_option(
148
        "--verbose", "-v", action="store",
149
        type="int", default=1, dest="verbose",
150
        help="Print detailed output messages")
151
    parser.add_option(
152
        "--version", action="store_true",
153
        default=False, dest="show_version",
154
        help="Show version and exit")
155
    parser.add_option(
156
        "--set-tests", action="callback", callback=parse_comma,
157
        type="string", default="all", dest="tests",
158
        help="Set comma separated tests for this run. Available tests: %s"
159
             % ", ".join(TSUITES_NAMES))
160
    parser.add_option(
161
        "--exclude-tests", action="callback", callback=parse_comma,
162
        type="string", default=None, dest="exclude_tests",
163
        help="Set comma separated tests to be excluded for this run.")
164
    parser.add_option(
165
        "--no-colors", action="store_false",
166
        default=True, dest="use_colors",
167
        help="Disable colorful output")
168
    parser.add_option(
169
        "--quiet", action="store_true",
170
        default=False, dest="quiet",
171
        help="Turn off log output")
172
    parser.add_option(
173
        "--final-report-only", action="store_true",
174
        default=False, dest="final_report",
175
        help="Turn off log output and only print the contents of the log "
176
             "file at the end of the test. Useful when burnin is used in "
177
             "script files and it's output is to be sent using email")
178

    
179
    (opts, args) = parser.parse_args(args)
180

    
181
    # ----------------------------------
182
    # Verify arguments
183
    # If `version' is given show version and exit
184
    if opts.show_version:
185
        show_version()
186
        sys.exit(0)
187

    
188
    # `delete_stale' implies `show_stale'
189
    if opts.delete_stale:
190
        opts.show_stale = True
191

    
192
    # `quiet' implies not `final_report'
193
    if opts.quiet:
194
        opts.final_report = False
195
    # `final_report' implies `quiet'
196
    if opts.final_report:
197
        opts.quiet = True
198

    
199
    # `token' is mandatory
200
    mandatory_argument(opts.token, "--token")
201
    # `auth_url' is mandatory
202
    mandatory_argument(opts.auth_url, "--auth-url")
203

    
204
    return (opts, args)
205

    
206

    
207
def show_version():
208
    """Show burnin's version"""
209
    sys.stdout.write("Burnin: version %s\n" % version.__version__)
210

    
211

    
212
def mandatory_argument(value, arg_name):
213
    """Check if a mandatory argument is given"""
214
    if (value is None) or (value == ""):
215
        sys.stderr.write("The " + arg_name + " argument is mandatory.\n")
216
        sys.exit("Invalid input")
217

    
218

    
219
# --------------------------------------------------------------------
220
# Burnin main function
221
def main():
222
    """Assemble test cases into a test suite, and run it
223

224
    IMPORTANT: Tests have dependencies and have to be run in the specified
225
    order inside a single test case. They communicate through attributes of the
226
    corresponding TestCase class (shared fixtures). Distinct subclasses of
227
    TestCase MAY SHARE NO DATA, since they are run in parallel, in distinct
228
    test runner processes.
229

230
    """
231

    
232
    # Parse arguments using `optparse'
233
    (opts, _) = parse_arguments(sys.argv[1:])
234

    
235
    # Initialize burnin
236
    testsuites = common.initialize(opts, TSUITES_NAMES)
237
    testsuites = string_to_class(testsuites)
238

    
239
    # Run burnin
240
    # The return value denotes the success status
241
    return common.run(testsuites, failfast=opts.failfast,
242
                      final_report=opts.final_report)
243

    
244

    
245
if __name__ == "__main__":
246
    sys.exit(main())