root / snf-tools / synnefo_tools / burnin / common.py @ 12ef696f
History | View | Annotate | Download (7.5 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 |
Common utils for burnin tests
|
36 |
|
37 |
"""
|
38 |
|
39 |
import sys |
40 |
import traceback |
41 |
# Use backported unittest functionality if Python < 2.7
|
42 |
try:
|
43 |
import unittest2 as unittest |
44 |
except ImportError: |
45 |
if sys.version_info < (2, 7): |
46 |
raise Exception("The unittest2 package is required for Python < 2.7") |
47 |
import unittest |
48 |
|
49 |
from kamaki.clients.astakos import AstakosClient |
50 |
from kamaki.clients.compute import ComputeClient |
51 |
|
52 |
from synnefo_tools.burnin.logger import Log |
53 |
|
54 |
|
55 |
# --------------------------------------------------------------------
|
56 |
# Global variables
|
57 |
logger = None # Invalid constant name. pylint: disable-msg=C0103 |
58 |
SNF_TEST_PREFIX = "snf-test-"
|
59 |
CONNECTION_RETRY_LIMIT = 2
|
60 |
|
61 |
|
62 |
# --------------------------------------------------------------------
|
63 |
# BurninTestResult class
|
64 |
class BurninTestResult(unittest.TestResult): |
65 |
"""Modify the TextTestResult class"""
|
66 |
def __init__(self): |
67 |
super(BurninTestResult, self).__init__() |
68 |
|
69 |
# Test parameters
|
70 |
self.failfast = True |
71 |
|
72 |
def startTest(self, test): # noqa |
73 |
"""Called when the test case test is about to be run"""
|
74 |
super(BurninTestResult, self).startTest(test) |
75 |
# Access to a protected member. pylint: disable-msg=W0212
|
76 |
logger.log(test.__class__.__name__, test._testMethodDoc) |
77 |
|
78 |
# Method could be a function. pylint: disable-msg=R0201
|
79 |
def _test_failed(self, test, err): |
80 |
"""Test failed"""
|
81 |
# Access to a protected member. pylint: disable-msg=W0212
|
82 |
err_msg = test._testMethodDoc + "... failed."
|
83 |
logger.error(test.__class__.__name__, err_msg) |
84 |
(err_type, err_value, err_trace) = err |
85 |
trcback = traceback.format_exception(err_type, err_value, err_trace) |
86 |
logger.info(test.__class__.__name__, trcback) |
87 |
|
88 |
def addError(self, test, err): # noqa |
89 |
"""Called when the test case test raises an unexpected exception"""
|
90 |
super(BurninTestResult, self).addError(test, err) |
91 |
self._test_failed(test, err)
|
92 |
|
93 |
def addFailure(self, test, err): # noqa |
94 |
"""Called when the test case test signals a failure"""
|
95 |
super(BurninTestResult, self).addFailure(test, err) |
96 |
self._test_failed(test, err)
|
97 |
|
98 |
|
99 |
# --------------------------------------------------------------------
|
100 |
# BurninTests class
|
101 |
# Too few public methods (0/2). pylint: disable-msg=R0903
|
102 |
class Clients(object): |
103 |
"""Our kamaki clients"""
|
104 |
auth_url = None
|
105 |
token = None
|
106 |
|
107 |
astakos = None
|
108 |
retry = CONNECTION_RETRY_LIMIT |
109 |
|
110 |
compute = None
|
111 |
compute_url = None
|
112 |
|
113 |
|
114 |
# Too many public methods (45/20). pylint: disable-msg=R0904
|
115 |
class BurninTests(unittest.TestCase): |
116 |
"""Common class that all burnin tests should implement"""
|
117 |
clients = Clients() |
118 |
opts = None
|
119 |
|
120 |
@classmethod
|
121 |
def setUpClass(cls): # noqa |
122 |
"""Initialize BurninTests"""
|
123 |
cls.suite_name = cls.__name__ |
124 |
logger.testsuite_start(cls.suite_name) |
125 |
|
126 |
# Set test parameters
|
127 |
cls.longMessage = True
|
128 |
|
129 |
def test_clients_setup(self): |
130 |
"""Initializing astakos/cyclades/pithos clients"""
|
131 |
# Update class attributes
|
132 |
self.info("Astakos auth url is %s", self.clients.auth_url) |
133 |
self.clients.astakos = AstakosClient(
|
134 |
self.clients.auth_url, self.clients.token) |
135 |
self.clients.astakos.CONNECTION_RETRY_LIMIT = self.clients.retry |
136 |
|
137 |
self.clients.compute_url = \
|
138 |
self.clients.astakos.get_service_endpoints('compute')['publicURL'] |
139 |
self.info("Cyclades url is %s", self.clients.compute_url) |
140 |
self.clients.compute = ComputeClient(
|
141 |
self.clients.compute_url, self.clients.token) |
142 |
self.clients.compute.CONNECTION_RETRY_LIMIT = self.clients.retry |
143 |
|
144 |
def log(self, msg, *args): |
145 |
"""Pass the section value to logger"""
|
146 |
logger.log(self.suite_name, msg, *args)
|
147 |
|
148 |
def info(self, msg, *args): |
149 |
"""Pass the section value to logger"""
|
150 |
logger.info(self.suite_name, msg, *args)
|
151 |
|
152 |
def debug(self, msg, *args): |
153 |
"""Pass the section value to logger"""
|
154 |
logger.debug(self.suite_name, msg, *args)
|
155 |
|
156 |
def warning(self, msg, *args): |
157 |
"""Pass the section value to logger"""
|
158 |
logger.warning(self.suite_name, msg, *args)
|
159 |
|
160 |
def error(self, msg, *args): |
161 |
"""Pass the section value to logger"""
|
162 |
logger.error(self.suite_name, msg, *args)
|
163 |
|
164 |
|
165 |
# --------------------------------------------------------------------
|
166 |
# Initialize Burnin
|
167 |
def initialize(opts, testsuites): |
168 |
"""Initalize burnin
|
169 |
|
170 |
Initialize our logger and burnin state
|
171 |
|
172 |
"""
|
173 |
# Initialize logger
|
174 |
global logger # Using global statement. pylint: disable-msg=C0103,W0603 |
175 |
logger = Log(opts.log_folder, verbose=opts.verbose, |
176 |
use_colors=opts.use_colors, in_parallel=False)
|
177 |
|
178 |
# Initialize clients
|
179 |
Clients.auth_url = opts.auth_url |
180 |
Clients.token = opts.token |
181 |
|
182 |
# Pass the rest options to BurninTests
|
183 |
BurninTests.opts = opts |
184 |
|
185 |
# Choose tests to run
|
186 |
if opts.tests != "all": |
187 |
testsuites = opts.tests |
188 |
if opts.exclude_tests is not None: |
189 |
testsuites = [tsuite for tsuite in testsuites |
190 |
if tsuite not in opts.exclude_tests] |
191 |
|
192 |
return testsuites
|
193 |
|
194 |
|
195 |
# --------------------------------------------------------------------
|
196 |
# Run Burnin
|
197 |
def run(testsuites): |
198 |
"""Run burnin testsuites"""
|
199 |
global logger # Using global. pylint: disable-msg=C0103,W0603,W0602 |
200 |
|
201 |
success = True
|
202 |
for tcase in testsuites: |
203 |
tsuite = unittest.TestLoader().loadTestsFromTestCase(tcase) |
204 |
results = tsuite.run(BurninTestResult()) |
205 |
success = success and \
|
206 |
was_successful(tcase.__name__, results.wasSuccessful()) |
207 |
|
208 |
# Clean up our logger
|
209 |
del(logger)
|
210 |
|
211 |
# Return
|
212 |
return 0 if success else 1 |
213 |
|
214 |
|
215 |
# --------------------------------------------------------------------
|
216 |
# Helper functions
|
217 |
def was_successful(tsuite, success): |
218 |
"""Handle whether a testsuite was succesful or not"""
|
219 |
if success:
|
220 |
logger.testsuite_success(tsuite) |
221 |
return True |
222 |
else:
|
223 |
logger.testsuite_failure(tsuite) |
224 |
return False |