Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin / __init__.py @ 9355a604

History | View | Annotate | Download (10.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
from synnefo_tools.burnin.server_tests import ServerTestSuite
49
from synnefo_tools.burnin.network_tests import NetworkTestSuite
50
from synnefo_tools.burnin.stale_tests import \
51
    StaleServersTestSuite, StaleFloatingIPsTestSuite, StaleNetworksTestSuite
52

    
53

    
54
# --------------------------------------------------------------------
55
# Define our TestSuites
56
TESTSUITES = [
57
    AstakosTestSuite,
58
    FlavorsTestSuite,
59
    ImagesTestSuite,
60
    PithosTestSuite,
61
    ServerTestSuite,
62
    NetworkTestSuite,
63
]
64
TSUITES_NAMES = [tsuite.__name__ for tsuite in TESTSUITES]
65

    
66
STALE_TESTSUITES = [
67
    # Must be runned in this order
68
    StaleServersTestSuite,
69
    StaleFloatingIPsTestSuite,
70
    StaleNetworksTestSuite,
71
]
72
STALE_TSUITES_NAMES = [tsuite.__name__ for tsuite in STALE_TESTSUITES]
73

    
74

    
75
def string_to_class(names):
76
    """Convert class namesto class objects"""
77
    return [eval(name) for name in names]
78

    
79

    
80
# --------------------------------------------------------------------
81
# Parse arguments
82
def parse_comma(option, _, value, parser):
83
    """Parse comma separated arguments"""
84
    parse_input = [p.strip() for p in value.split(',')]
85
    setattr(parser.values, option.dest, parse_input)
86

    
87

    
88
def parse_arguments(args):
89
    """Parse burnin arguments"""
90
    kwargs = {}
91
    kwargs["usage"] = "%prog [options]"
92
    kwargs["description"] = \
93
        "%prog runs a number of test scenarios on a Synnefo deployment."
94

    
95
    parser = optparse.OptionParser(**kwargs)  # pylint: disable=star-args
96
    parser.disable_interspersed_args()
97

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

    
197
    (opts, args) = parser.parse_args(args)
198

    
199
    # ----------------------------------
200
    # Verify arguments
201
    # If `version' is given show version and exit
202
    if opts.show_version:
203
        show_version()
204
        sys.exit(0)
205

    
206
    # `delete_stale' implies `show_stale'
207
    if opts.delete_stale:
208
        opts.show_stale = True
209

    
210
    # log_level:
211
    #  0 -> log to console and file
212
    #  1 -> log to file and output the results in console
213
    #  2 -> don't log
214
    opts.log_level = 0
215
    if opts.final_report:
216
        opts.log_level = 1
217
    if opts.quiet:
218
        opts.log_level = 2
219

    
220
    # Check `--set-tests' and `--exclude-tests' options
221
    if opts.tests != "all" and \
222
            not (set(opts.tests)).issubset(set(TSUITES_NAMES)):
223
        raise optparse.OptionValueError("The selected set of tests is invalid")
224
    if opts.exclude_tests is not None and \
225
            not (set(opts.exclude_tests)).issubset(set(TSUITES_NAMES)):
226
        raise optparse.OptionValueError("The selected set of tests is invalid")
227

    
228
    # `token' is mandatory
229
    mandatory_argument(opts.token, "--token")
230
    # `auth_url' is mandatory
231
    mandatory_argument(opts.auth_url, "--auth-url")
232

    
233
    return (opts, args)
234

    
235

    
236
def show_version():
237
    """Show burnin's version"""
238
    sys.stdout.write("Burnin: version %s\n" % version.__version__)
239

    
240

    
241
def mandatory_argument(value, arg_name):
242
    """Check if a mandatory argument is given"""
243
    if (value is None) or (value == ""):
244
        sys.stderr.write("The " + arg_name + " argument is mandatory.\n")
245
        sys.exit("Invalid input")
246

    
247

    
248
# --------------------------------------------------------------------
249
# Burnin main function
250
def main():
251
    """Assemble test cases into a test suite, and run it
252

253
    IMPORTANT: Tests have dependencies and have to be run in the specified
254
    order inside a single test case. They communicate through attributes of the
255
    corresponding TestCase class (shared fixtures). Distinct subclasses of
256
    TestCase MAY SHARE NO DATA, since they are run in parallel, in distinct
257
    test runner processes.
258

259
    """
260

    
261
    # Parse arguments using `optparse'
262
    (opts, _) = parse_arguments(sys.argv[1:])
263

    
264
    # Initialize burnin
265
    (testsuites, failfast) = \
266
        common.initialize(opts, TSUITES_NAMES, STALE_TSUITES_NAMES)
267
    testsuites = string_to_class(testsuites)
268

    
269
    # Run burnin
270
    # The return value denotes the success status
271
    return common.run_burnin(testsuites, failfast=failfast)
272

    
273

    
274
if __name__ == "__main__":
275
    sys.exit(main())