Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin / __init__.py @ 0c1833c8

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 AstakosTestCase, AstakosFoo
45

    
46

    
47
# --------------------------------------------------------------------
48
# Define our TestSuites
49
TESTSUITES = [
50
    AstakosTestCase, AstakosFoo
51
    ]
52

    
53
TSUITES_NAMES = [tsuite.__name__ for tsuite in TESTSUITES]
54

    
55

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

    
60

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

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

    
71
    setattr(parser.values, option.dest, value.split(','))
72

    
73

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

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

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

    
175
    (opts, args) = parser.parse_args(args)
176

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

    
184
    # `delete_stale' implies `show_stale'
185
    if opts.delete_stale:
186
        opts.show_stale = True
187

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

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

    
200
    return (opts, args)
201

    
202

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

    
207

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

    
214

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

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

226
    """
227

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

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

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

    
240

    
241
if __name__ == "__main__":
242
    sys.exit(main())