Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin / __init__.py @ fe15cd00

History | View | Annotate | Download (9 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

    
47

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

    
55
TSUITES_NAMES = [tsuite.__name__ for tsuite in TESTSUITES]
56

    
57

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

    
62

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

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

    
73
    setattr(parser.values, option.dest, value.split(','))
74

    
75

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

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

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

    
177
    (opts, args) = parser.parse_args(args)
178

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

    
186
    # `delete_stale' implies `show_stale'
187
    if opts.delete_stale:
188
        opts.show_stale = True
189

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

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

    
202
    return (opts, args)
203

    
204

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

    
209

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

    
216

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

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

228
    """
229

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

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

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

    
242

    
243
if __name__ == "__main__":
244
    sys.exit(main())