Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (9.4 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.images_tests import \
46
    FlavorsTestSuite, ImagesTestSuite
47
from synnefo_tools.burnin.pithos_tests import PithosTestSuite
48

    
49

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

    
59
TSUITES_NAMES = [tsuite.__name__ for tsuite in TESTSUITES]
60

    
61

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

    
66

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

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

    
77
    setattr(parser.values, option.dest, value.split(','))
78

    
79

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

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

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

    
186
    (opts, args) = parser.parse_args(args)
187

    
188
    # ----------------------------------
189
    # Verify arguments
190
    # If `version' is given show version and exit
191
    if opts.show_version:
192
        show_version()
193
        sys.exit(0)
194

    
195
    # `delete_stale' implies `show_stale'
196
    if opts.delete_stale:
197
        opts.show_stale = True
198

    
199
    # `quiet' implies not `final_report'
200
    if opts.quiet:
201
        opts.final_report = False
202
    # `final_report' implies `quiet'
203
    if opts.final_report:
204
        opts.quiet = True
205

    
206
    # `token' is mandatory
207
    mandatory_argument(opts.token, "--token")
208
    # `auth_url' is mandatory
209
    mandatory_argument(opts.auth_url, "--auth-url")
210

    
211
    return (opts, args)
212

    
213

    
214
def show_version():
215
    """Show burnin's version"""
216
    sys.stdout.write("Burnin: version %s\n" % version.__version__)
217

    
218

    
219
def mandatory_argument(value, arg_name):
220
    """Check if a mandatory argument is given"""
221
    if (value is None) or (value == ""):
222
        sys.stderr.write("The " + arg_name + " argument is mandatory.\n")
223
        sys.exit("Invalid input")
224

    
225

    
226
# --------------------------------------------------------------------
227
# Burnin main function
228
def main():
229
    """Assemble test cases into a test suite, and run it
230

231
    IMPORTANT: Tests have dependencies and have to be run in the specified
232
    order inside a single test case. They communicate through attributes of the
233
    corresponding TestCase class (shared fixtures). Distinct subclasses of
234
    TestCase MAY SHARE NO DATA, since they are run in parallel, in distinct
235
    test runner processes.
236

237
    """
238

    
239
    # Parse arguments using `optparse'
240
    (opts, _) = parse_arguments(sys.argv[1:])
241

    
242
    # Initialize burnin
243
    testsuites = common.initialize(opts, TSUITES_NAMES)
244
    testsuites = string_to_class(testsuites)
245

    
246
    # Run burnin
247
    # The return value denotes the success status
248
    return common.run(testsuites, failfast=opts.failfast,
249
                      final_report=opts.final_report)
250

    
251

    
252
if __name__ == "__main__":
253
    sys.exit(main())