root / snf-tools / synnefo_tools / burnin / common.py @ d11c80c0
History | View | Annotate | Download (16.8 kB)
1 | 4c52d5bf | Ilias Tsitsimpis | # Copyright 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 4c52d5bf | Ilias Tsitsimpis | #
|
3 | 4c52d5bf | Ilias Tsitsimpis | # Redistribution and use in source and binary forms, with or
|
4 | 4c52d5bf | Ilias Tsitsimpis | # without modification, are permitted provided that the following
|
5 | 4c52d5bf | Ilias Tsitsimpis | # conditions are met:
|
6 | 4c52d5bf | Ilias Tsitsimpis | #
|
7 | 4c52d5bf | Ilias Tsitsimpis | # 1. Redistributions of source code must retain the above
|
8 | 4c52d5bf | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
9 | 4c52d5bf | Ilias Tsitsimpis | # disclaimer.
|
10 | 4c52d5bf | Ilias Tsitsimpis | #
|
11 | 4c52d5bf | Ilias Tsitsimpis | # 2. Redistributions in binary form must reproduce the above
|
12 | 4c52d5bf | Ilias Tsitsimpis | # copyright notice, this list of conditions and the following
|
13 | 4c52d5bf | Ilias Tsitsimpis | # disclaimer in the documentation and/or other materials
|
14 | 4c52d5bf | Ilias Tsitsimpis | # provided with the distribution.
|
15 | 4c52d5bf | Ilias Tsitsimpis | #
|
16 | 4c52d5bf | Ilias Tsitsimpis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
17 | 4c52d5bf | Ilias Tsitsimpis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
18 | 4c52d5bf | Ilias Tsitsimpis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
19 | 4c52d5bf | Ilias Tsitsimpis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
20 | 4c52d5bf | Ilias Tsitsimpis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
21 | 4c52d5bf | Ilias Tsitsimpis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
22 | 4c52d5bf | Ilias Tsitsimpis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
23 | 4c52d5bf | Ilias Tsitsimpis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
24 | 4c52d5bf | Ilias Tsitsimpis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 | 4c52d5bf | Ilias Tsitsimpis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
26 | 4c52d5bf | Ilias Tsitsimpis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
27 | 4c52d5bf | Ilias Tsitsimpis | # POSSIBILITY OF SUCH DAMAGE.
|
28 | 4c52d5bf | Ilias Tsitsimpis | #
|
29 | 4c52d5bf | Ilias Tsitsimpis | # The views and conclusions contained in the software and
|
30 | 4c52d5bf | Ilias Tsitsimpis | # documentation are those of the authors and should not be
|
31 | 4c52d5bf | Ilias Tsitsimpis | # interpreted as representing official policies, either expressed
|
32 | 4c52d5bf | Ilias Tsitsimpis | # or implied, of GRNET S.A.
|
33 | 4c52d5bf | Ilias Tsitsimpis | |
34 | 4c52d5bf | Ilias Tsitsimpis | """
|
35 | 4c52d5bf | Ilias Tsitsimpis | Common utils for burnin tests
|
36 | 4c52d5bf | Ilias Tsitsimpis |
|
37 | 4c52d5bf | Ilias Tsitsimpis | """
|
38 | 4c52d5bf | Ilias Tsitsimpis | |
39 | f772699c | Ilias Tsitsimpis | import os |
40 | f772699c | Ilias Tsitsimpis | import re |
41 | f772699c | Ilias Tsitsimpis | import shutil |
42 | d11c80c0 | Ilias Tsitsimpis | import unittest |
43 | 6f2b9836 | Ilias Tsitsimpis | import datetime |
44 | f772699c | Ilias Tsitsimpis | import tempfile |
45 | 4c52d5bf | Ilias Tsitsimpis | import traceback |
46 | 4c52d5bf | Ilias Tsitsimpis | |
47 | 4c52d5bf | Ilias Tsitsimpis | from kamaki.clients.astakos import AstakosClient |
48 | 4c52d5bf | Ilias Tsitsimpis | from kamaki.clients.compute import ComputeClient |
49 | 79a5c431 | Ilias Tsitsimpis | from kamaki.clients.pithos import PithosClient |
50 | f772699c | Ilias Tsitsimpis | from kamaki.clients.image import ImageClient |
51 | 4c52d5bf | Ilias Tsitsimpis | |
52 | 12ef696f | Ilias Tsitsimpis | from synnefo_tools.burnin.logger import Log |
53 | 4c52d5bf | Ilias Tsitsimpis | |
54 | 4c52d5bf | Ilias Tsitsimpis | |
55 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
56 | 4c52d5bf | Ilias Tsitsimpis | # Global variables
|
57 | 4c52d5bf | Ilias Tsitsimpis | logger = None # Invalid constant name. pylint: disable-msg=C0103 |
58 | 12ef696f | Ilias Tsitsimpis | SNF_TEST_PREFIX = "snf-test-"
|
59 | 4c52d5bf | Ilias Tsitsimpis | CONNECTION_RETRY_LIMIT = 2
|
60 | f772699c | Ilias Tsitsimpis | SYSTEM_USERS = ["images@okeanos.grnet.gr", "images@demo.synnefo.org"] |
61 | 4c52d5bf | Ilias Tsitsimpis | |
62 | 4c52d5bf | Ilias Tsitsimpis | |
63 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
64 | 4c52d5bf | Ilias Tsitsimpis | # BurninTestResult class
|
65 | 4c52d5bf | Ilias Tsitsimpis | class BurninTestResult(unittest.TestResult): |
66 | 4c52d5bf | Ilias Tsitsimpis | """Modify the TextTestResult class"""
|
67 | 4c52d5bf | Ilias Tsitsimpis | def __init__(self): |
68 | 4c52d5bf | Ilias Tsitsimpis | super(BurninTestResult, self).__init__() |
69 | 4c52d5bf | Ilias Tsitsimpis | |
70 | 4c52d5bf | Ilias Tsitsimpis | # Test parameters
|
71 | 4c52d5bf | Ilias Tsitsimpis | self.failfast = True |
72 | 4c52d5bf | Ilias Tsitsimpis | |
73 | 4c52d5bf | Ilias Tsitsimpis | def startTest(self, test): # noqa |
74 | 4c52d5bf | Ilias Tsitsimpis | """Called when the test case test is about to be run"""
|
75 | 4c52d5bf | Ilias Tsitsimpis | super(BurninTestResult, self).startTest(test) |
76 | fe15cd00 | Ilias Tsitsimpis | logger.log(test.__class__.__name__, test.shortDescription()) |
77 | 4c52d5bf | Ilias Tsitsimpis | |
78 | 4c52d5bf | Ilias Tsitsimpis | # Method could be a function. pylint: disable-msg=R0201
|
79 | 4c52d5bf | Ilias Tsitsimpis | def _test_failed(self, test, err): |
80 | 4c52d5bf | Ilias Tsitsimpis | """Test failed"""
|
81 | 79a5c431 | Ilias Tsitsimpis | # Get class name
|
82 | 79a5c431 | Ilias Tsitsimpis | if test.__class__.__name__ == "_ErrorHolder": |
83 | 79a5c431 | Ilias Tsitsimpis | class_name = test.id().split('.')[-1].rstrip(')') |
84 | 79a5c431 | Ilias Tsitsimpis | else:
|
85 | 79a5c431 | Ilias Tsitsimpis | class_name = test.__class__.__name__ |
86 | fe15cd00 | Ilias Tsitsimpis | err_msg = str(test) + "... failed (%s)." |
87 | 6f2b9836 | Ilias Tsitsimpis | timestamp = datetime.datetime.strftime( |
88 | 6f2b9836 | Ilias Tsitsimpis | datetime.datetime.now(), "%a %b %d %Y %H:%M:%S")
|
89 | 79a5c431 | Ilias Tsitsimpis | logger.error(class_name, err_msg, timestamp) |
90 | 4c52d5bf | Ilias Tsitsimpis | (err_type, err_value, err_trace) = err |
91 | 4c52d5bf | Ilias Tsitsimpis | trcback = traceback.format_exception(err_type, err_value, err_trace) |
92 | 79a5c431 | Ilias Tsitsimpis | logger.info(class_name, trcback) |
93 | 4c52d5bf | Ilias Tsitsimpis | |
94 | 4c52d5bf | Ilias Tsitsimpis | def addError(self, test, err): # noqa |
95 | 4c52d5bf | Ilias Tsitsimpis | """Called when the test case test raises an unexpected exception"""
|
96 | 4c52d5bf | Ilias Tsitsimpis | super(BurninTestResult, self).addError(test, err) |
97 | 4c52d5bf | Ilias Tsitsimpis | self._test_failed(test, err)
|
98 | 4c52d5bf | Ilias Tsitsimpis | |
99 | 4c52d5bf | Ilias Tsitsimpis | def addFailure(self, test, err): # noqa |
100 | 4c52d5bf | Ilias Tsitsimpis | """Called when the test case test signals a failure"""
|
101 | 4c52d5bf | Ilias Tsitsimpis | super(BurninTestResult, self).addFailure(test, err) |
102 | 4c52d5bf | Ilias Tsitsimpis | self._test_failed(test, err)
|
103 | 4c52d5bf | Ilias Tsitsimpis | |
104 | 4c52d5bf | Ilias Tsitsimpis | |
105 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
106 | 4c52d5bf | Ilias Tsitsimpis | # BurninTests class
|
107 | 12ef696f | Ilias Tsitsimpis | # Too few public methods (0/2). pylint: disable-msg=R0903
|
108 | 12ef696f | Ilias Tsitsimpis | class Clients(object): |
109 | 12ef696f | Ilias Tsitsimpis | """Our kamaki clients"""
|
110 | 12ef696f | Ilias Tsitsimpis | auth_url = None
|
111 | 12ef696f | Ilias Tsitsimpis | token = None
|
112 | 79a5c431 | Ilias Tsitsimpis | # Astakos
|
113 | 12ef696f | Ilias Tsitsimpis | astakos = None
|
114 | 12ef696f | Ilias Tsitsimpis | retry = CONNECTION_RETRY_LIMIT |
115 | 79a5c431 | Ilias Tsitsimpis | # Compute
|
116 | 12ef696f | Ilias Tsitsimpis | compute = None
|
117 | 12ef696f | Ilias Tsitsimpis | compute_url = None
|
118 | 79a5c431 | Ilias Tsitsimpis | # Cyclades
|
119 | 79a5c431 | Ilias Tsitsimpis | cyclades = None
|
120 | 79a5c431 | Ilias Tsitsimpis | # Pithos
|
121 | 79a5c431 | Ilias Tsitsimpis | pithos = None
|
122 | 79a5c431 | Ilias Tsitsimpis | pithos_url = None
|
123 | f772699c | Ilias Tsitsimpis | # Image
|
124 | f772699c | Ilias Tsitsimpis | image = None
|
125 | f772699c | Ilias Tsitsimpis | image_url = None
|
126 | 12ef696f | Ilias Tsitsimpis | |
127 | 12ef696f | Ilias Tsitsimpis | |
128 | 4c52d5bf | Ilias Tsitsimpis | # Too many public methods (45/20). pylint: disable-msg=R0904
|
129 | 4c52d5bf | Ilias Tsitsimpis | class BurninTests(unittest.TestCase): |
130 | 4c52d5bf | Ilias Tsitsimpis | """Common class that all burnin tests should implement"""
|
131 | 12ef696f | Ilias Tsitsimpis | clients = Clients() |
132 | 6f2b9836 | Ilias Tsitsimpis | run_id = None
|
133 | 79a5c431 | Ilias Tsitsimpis | use_ipv6 = None
|
134 | 79a5c431 | Ilias Tsitsimpis | action_timeout = None
|
135 | 79a5c431 | Ilias Tsitsimpis | action_warning = None
|
136 | 79a5c431 | Ilias Tsitsimpis | query_interval = None
|
137 | f772699c | Ilias Tsitsimpis | system_user = None
|
138 | 12ef696f | Ilias Tsitsimpis | |
139 | 4c52d5bf | Ilias Tsitsimpis | @classmethod
|
140 | 4c52d5bf | Ilias Tsitsimpis | def setUpClass(cls): # noqa |
141 | 4c52d5bf | Ilias Tsitsimpis | """Initialize BurninTests"""
|
142 | 4c52d5bf | Ilias Tsitsimpis | cls.suite_name = cls.__name__ |
143 | 4c52d5bf | Ilias Tsitsimpis | logger.testsuite_start(cls.suite_name) |
144 | 4c52d5bf | Ilias Tsitsimpis | |
145 | 4c52d5bf | Ilias Tsitsimpis | # Set test parameters
|
146 | 4c52d5bf | Ilias Tsitsimpis | cls.longMessage = True
|
147 | 4c52d5bf | Ilias Tsitsimpis | |
148 | fe15cd00 | Ilias Tsitsimpis | def test_000_clients_setup(self): |
149 | 4c52d5bf | Ilias Tsitsimpis | """Initializing astakos/cyclades/pithos clients"""
|
150 | 4c52d5bf | Ilias Tsitsimpis | # Update class attributes
|
151 | 12ef696f | Ilias Tsitsimpis | self.info("Astakos auth url is %s", self.clients.auth_url) |
152 | 12ef696f | Ilias Tsitsimpis | self.clients.astakos = AstakosClient(
|
153 | 12ef696f | Ilias Tsitsimpis | self.clients.auth_url, self.clients.token) |
154 | 12ef696f | Ilias Tsitsimpis | self.clients.astakos.CONNECTION_RETRY_LIMIT = self.clients.retry |
155 | 12ef696f | Ilias Tsitsimpis | |
156 | 12ef696f | Ilias Tsitsimpis | self.clients.compute_url = \
|
157 | 12ef696f | Ilias Tsitsimpis | self.clients.astakos.get_service_endpoints('compute')['publicURL'] |
158 | 12ef696f | Ilias Tsitsimpis | self.info("Cyclades url is %s", self.clients.compute_url) |
159 | 12ef696f | Ilias Tsitsimpis | self.clients.compute = ComputeClient(
|
160 | 12ef696f | Ilias Tsitsimpis | self.clients.compute_url, self.clients.token) |
161 | 12ef696f | Ilias Tsitsimpis | self.clients.compute.CONNECTION_RETRY_LIMIT = self.clients.retry |
162 | 4c52d5bf | Ilias Tsitsimpis | |
163 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos_url = self.clients.astakos.\ |
164 | 79a5c431 | Ilias Tsitsimpis | get_service_endpoints('object-store')['publicURL'] |
165 | 79a5c431 | Ilias Tsitsimpis | self.info("Pithos url is %s", self.clients.pithos_url) |
166 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos = PithosClient(
|
167 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos_url, self.clients.token) |
168 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos.CONNECTION_RETRY_LIMIT = self.clients.retry |
169 | 79a5c431 | Ilias Tsitsimpis | |
170 | f772699c | Ilias Tsitsimpis | self.clients.image_url = \
|
171 | f772699c | Ilias Tsitsimpis | self.clients.astakos.get_service_endpoints('image')['publicURL'] |
172 | f772699c | Ilias Tsitsimpis | self.info("Image url is %s", self.clients.image_url) |
173 | f772699c | Ilias Tsitsimpis | self.clients.image = ImageClient(
|
174 | f772699c | Ilias Tsitsimpis | self.clients.image_url, self.clients.token) |
175 | f772699c | Ilias Tsitsimpis | self.clients.image.CONNECTION_RETRY_LIMIT = self.clients.retry |
176 | f772699c | Ilias Tsitsimpis | |
177 | 6f2b9836 | Ilias Tsitsimpis | # ----------------------------------
|
178 | 6f2b9836 | Ilias Tsitsimpis | # Loggers helper functions
|
179 | 4c52d5bf | Ilias Tsitsimpis | def log(self, msg, *args): |
180 | 4c52d5bf | Ilias Tsitsimpis | """Pass the section value to logger"""
|
181 | 4c52d5bf | Ilias Tsitsimpis | logger.log(self.suite_name, msg, *args)
|
182 | 4c52d5bf | Ilias Tsitsimpis | |
183 | 4c52d5bf | Ilias Tsitsimpis | def info(self, msg, *args): |
184 | 4c52d5bf | Ilias Tsitsimpis | """Pass the section value to logger"""
|
185 | 4c52d5bf | Ilias Tsitsimpis | logger.info(self.suite_name, msg, *args)
|
186 | 4c52d5bf | Ilias Tsitsimpis | |
187 | 4c52d5bf | Ilias Tsitsimpis | def debug(self, msg, *args): |
188 | 4c52d5bf | Ilias Tsitsimpis | """Pass the section value to logger"""
|
189 | 4c52d5bf | Ilias Tsitsimpis | logger.debug(self.suite_name, msg, *args)
|
190 | 4c52d5bf | Ilias Tsitsimpis | |
191 | 4c52d5bf | Ilias Tsitsimpis | def warning(self, msg, *args): |
192 | 4c52d5bf | Ilias Tsitsimpis | """Pass the section value to logger"""
|
193 | 4c52d5bf | Ilias Tsitsimpis | logger.warning(self.suite_name, msg, *args)
|
194 | 4c52d5bf | Ilias Tsitsimpis | |
195 | 4c52d5bf | Ilias Tsitsimpis | def error(self, msg, *args): |
196 | 4c52d5bf | Ilias Tsitsimpis | """Pass the section value to logger"""
|
197 | 4c52d5bf | Ilias Tsitsimpis | logger.error(self.suite_name, msg, *args)
|
198 | 4c52d5bf | Ilias Tsitsimpis | |
199 | 6f2b9836 | Ilias Tsitsimpis | # ----------------------------------
|
200 | 6f2b9836 | Ilias Tsitsimpis | # Helper functions that every testsuite may need
|
201 | 6f2b9836 | Ilias Tsitsimpis | def _get_uuid(self): |
202 | 6f2b9836 | Ilias Tsitsimpis | """Get our uuid"""
|
203 | 6f2b9836 | Ilias Tsitsimpis | authenticate = self.clients.astakos.authenticate()
|
204 | 6f2b9836 | Ilias Tsitsimpis | uuid = authenticate['access']['user']['id'] |
205 | 6f2b9836 | Ilias Tsitsimpis | self.info("User's uuid is %s", uuid) |
206 | 6f2b9836 | Ilias Tsitsimpis | return uuid
|
207 | 6f2b9836 | Ilias Tsitsimpis | |
208 | 6f2b9836 | Ilias Tsitsimpis | def _get_username(self): |
209 | 6f2b9836 | Ilias Tsitsimpis | """Get our User Name"""
|
210 | 6f2b9836 | Ilias Tsitsimpis | authenticate = self.clients.astakos.authenticate()
|
211 | 6f2b9836 | Ilias Tsitsimpis | username = authenticate['access']['user']['name'] |
212 | 6f2b9836 | Ilias Tsitsimpis | self.info("User's name is %s", username) |
213 | 6f2b9836 | Ilias Tsitsimpis | return username
|
214 | 6f2b9836 | Ilias Tsitsimpis | |
215 | f772699c | Ilias Tsitsimpis | def _create_tmp_directory(self): |
216 | f772699c | Ilias Tsitsimpis | """Create a tmp directory
|
217 | f772699c | Ilias Tsitsimpis |
|
218 | f772699c | Ilias Tsitsimpis | In my machine /tmp has not enough space for an image
|
219 | f772699c | Ilias Tsitsimpis | to be saves, so we are going to use the current directory.
|
220 | f772699c | Ilias Tsitsimpis |
|
221 | f772699c | Ilias Tsitsimpis | """
|
222 | f772699c | Ilias Tsitsimpis | temp_dir = tempfile.mkdtemp(dir=os.getcwd()) |
223 | f772699c | Ilias Tsitsimpis | self.info("Temp directory %s created", temp_dir) |
224 | f772699c | Ilias Tsitsimpis | return temp_dir
|
225 | f772699c | Ilias Tsitsimpis | |
226 | f772699c | Ilias Tsitsimpis | def _remove_tmp_directory(self, tmp_dir): |
227 | f772699c | Ilias Tsitsimpis | """Remove a tmp directory"""
|
228 | f772699c | Ilias Tsitsimpis | try:
|
229 | f772699c | Ilias Tsitsimpis | shutil.rmtree(tmp_dir) |
230 | f772699c | Ilias Tsitsimpis | self.info("Temp directory %s deleted", tmp_dir) |
231 | f772699c | Ilias Tsitsimpis | except OSError: |
232 | f772699c | Ilias Tsitsimpis | pass
|
233 | f772699c | Ilias Tsitsimpis | |
234 | f772699c | Ilias Tsitsimpis | def _get_uuid_of_system_user(self): |
235 | f772699c | Ilias Tsitsimpis | """Get the uuid of the system user
|
236 | f772699c | Ilias Tsitsimpis |
|
237 | f772699c | Ilias Tsitsimpis | This is the user that upload the 'official' images.
|
238 | f772699c | Ilias Tsitsimpis |
|
239 | f772699c | Ilias Tsitsimpis | """
|
240 | f772699c | Ilias Tsitsimpis | self.info("Getting the uuid of the system user") |
241 | f772699c | Ilias Tsitsimpis | system_users = None
|
242 | f772699c | Ilias Tsitsimpis | if self.system_user is not None: |
243 | f772699c | Ilias Tsitsimpis | parsed_su = parse_typed_option(self.system_user)
|
244 | f772699c | Ilias Tsitsimpis | if parsed_su is None: |
245 | f772699c | Ilias Tsitsimpis | msg = "Invalid system-user format: %s. Must be [id|name]:.+"
|
246 | f772699c | Ilias Tsitsimpis | self.warning(msg, self.system_user) |
247 | f772699c | Ilias Tsitsimpis | else:
|
248 | f772699c | Ilias Tsitsimpis | su_type, su_value = parsed_su |
249 | f772699c | Ilias Tsitsimpis | if su_type == "name": |
250 | f772699c | Ilias Tsitsimpis | system_users = [su_value] |
251 | f772699c | Ilias Tsitsimpis | elif su_type == "id": |
252 | f772699c | Ilias Tsitsimpis | self.info("System user's uuid is %s", su_value) |
253 | f772699c | Ilias Tsitsimpis | return su_value
|
254 | f772699c | Ilias Tsitsimpis | else:
|
255 | f772699c | Ilias Tsitsimpis | self.error("Unrecognized system-user type %s", su_type) |
256 | f772699c | Ilias Tsitsimpis | self.fail("Unrecognized system-user type") |
257 | f772699c | Ilias Tsitsimpis | |
258 | f772699c | Ilias Tsitsimpis | if system_users is None: |
259 | f772699c | Ilias Tsitsimpis | system_users = SYSTEM_USERS |
260 | f772699c | Ilias Tsitsimpis | |
261 | f772699c | Ilias Tsitsimpis | uuids = self.clients.astakos.usernames2uuids(system_users)
|
262 | f772699c | Ilias Tsitsimpis | for su_name in system_users: |
263 | f772699c | Ilias Tsitsimpis | self.info("Trying username %s", su_name) |
264 | f772699c | Ilias Tsitsimpis | if su_name in uuids: |
265 | f772699c | Ilias Tsitsimpis | self.info("System user's uuid is %s", uuids[su_name]) |
266 | f772699c | Ilias Tsitsimpis | return uuids[su_name]
|
267 | f772699c | Ilias Tsitsimpis | |
268 | f772699c | Ilias Tsitsimpis | self.warning("No system user found") |
269 | f772699c | Ilias Tsitsimpis | return None |
270 | f772699c | Ilias Tsitsimpis | |
271 | f772699c | Ilias Tsitsimpis | # ----------------------------------
|
272 | f772699c | Ilias Tsitsimpis | # Flavors
|
273 | fe15cd00 | Ilias Tsitsimpis | def _get_list_of_flavors(self, detail=False): |
274 | fe15cd00 | Ilias Tsitsimpis | """Get (detailed) list of flavors"""
|
275 | fe15cd00 | Ilias Tsitsimpis | if detail:
|
276 | fe15cd00 | Ilias Tsitsimpis | self.info("Getting detailed list of flavors") |
277 | fe15cd00 | Ilias Tsitsimpis | else:
|
278 | fe15cd00 | Ilias Tsitsimpis | self.info("Getting simple list of flavors") |
279 | fe15cd00 | Ilias Tsitsimpis | flavors = self.clients.compute.list_flavors(detail=detail)
|
280 | fe15cd00 | Ilias Tsitsimpis | return flavors
|
281 | fe15cd00 | Ilias Tsitsimpis | |
282 | f772699c | Ilias Tsitsimpis | # ----------------------------------
|
283 | f772699c | Ilias Tsitsimpis | # Images
|
284 | f772699c | Ilias Tsitsimpis | def _get_list_of_images(self, detail=False): |
285 | f772699c | Ilias Tsitsimpis | """Get (detailed) list of images"""
|
286 | f772699c | Ilias Tsitsimpis | if detail:
|
287 | f772699c | Ilias Tsitsimpis | self.info("Getting detailed list of images") |
288 | f772699c | Ilias Tsitsimpis | else:
|
289 | f772699c | Ilias Tsitsimpis | self.info("Getting simple list of images") |
290 | f772699c | Ilias Tsitsimpis | images = self.clients.image.list_public(detail=detail)
|
291 | f772699c | Ilias Tsitsimpis | # Remove images registered by burnin
|
292 | f772699c | Ilias Tsitsimpis | images = [img for img in images |
293 | f772699c | Ilias Tsitsimpis | if not img['name'].startswith(SNF_TEST_PREFIX)] |
294 | f772699c | Ilias Tsitsimpis | return images
|
295 | f772699c | Ilias Tsitsimpis | |
296 | f772699c | Ilias Tsitsimpis | def _get_list_of_sys_images(self, images=None): |
297 | f772699c | Ilias Tsitsimpis | """Get (detailed) list of images registered by system user or by me"""
|
298 | f772699c | Ilias Tsitsimpis | self.info("Getting list of images registered by system user or by me") |
299 | f772699c | Ilias Tsitsimpis | if images is None: |
300 | f772699c | Ilias Tsitsimpis | images = self._get_list_of_images(detail=True) |
301 | f772699c | Ilias Tsitsimpis | |
302 | f772699c | Ilias Tsitsimpis | su_uuid = self._get_uuid_of_system_user()
|
303 | f772699c | Ilias Tsitsimpis | my_uuid = self._get_uuid()
|
304 | f772699c | Ilias Tsitsimpis | ret_images = [i for i in images |
305 | f772699c | Ilias Tsitsimpis | if i['owner'] == su_uuid or i['owner'] == my_uuid] |
306 | f772699c | Ilias Tsitsimpis | |
307 | f772699c | Ilias Tsitsimpis | return ret_images
|
308 | f772699c | Ilias Tsitsimpis | |
309 | f772699c | Ilias Tsitsimpis | def _find_image(self, patterns, images=None): |
310 | f772699c | Ilias Tsitsimpis | """Find a suitable image to use
|
311 | f772699c | Ilias Tsitsimpis |
|
312 | f772699c | Ilias Tsitsimpis | The patterns is a list of `typed_options'. The first pattern to
|
313 | f772699c | Ilias Tsitsimpis | match an image will be the one that will be returned.
|
314 | f772699c | Ilias Tsitsimpis |
|
315 | f772699c | Ilias Tsitsimpis | """
|
316 | f772699c | Ilias Tsitsimpis | if images is None: |
317 | f772699c | Ilias Tsitsimpis | images = self._get_list_of_sys_images()
|
318 | f772699c | Ilias Tsitsimpis | |
319 | f772699c | Ilias Tsitsimpis | for ptrn in patterns: |
320 | f772699c | Ilias Tsitsimpis | parsed_ptrn = parse_typed_option(ptrn) |
321 | f772699c | Ilias Tsitsimpis | if parsed_ptrn is None: |
322 | f772699c | Ilias Tsitsimpis | msg = "Invalid image format: %s. Must be [id|name]:.+"
|
323 | f772699c | Ilias Tsitsimpis | self.warning(msg, ptrn)
|
324 | f772699c | Ilias Tsitsimpis | continue
|
325 | f772699c | Ilias Tsitsimpis | img_type, img_value = parsed_ptrn |
326 | f772699c | Ilias Tsitsimpis | if img_type == "name": |
327 | f772699c | Ilias Tsitsimpis | # Filter image by name
|
328 | f772699c | Ilias Tsitsimpis | msg = "Trying to find an image with name %s"
|
329 | f772699c | Ilias Tsitsimpis | self.info(msg, img_value)
|
330 | f772699c | Ilias Tsitsimpis | filtered_imgs = \ |
331 | f772699c | Ilias Tsitsimpis | [i for i in images if |
332 | f772699c | Ilias Tsitsimpis | re.search(img_value, i['name'], flags=re.I) is not None] |
333 | f772699c | Ilias Tsitsimpis | elif img_type == "id": |
334 | f772699c | Ilias Tsitsimpis | # Filter images by id
|
335 | f772699c | Ilias Tsitsimpis | msg = "Trying to find an image with id %s"
|
336 | f772699c | Ilias Tsitsimpis | self.info(msg, img_value)
|
337 | f772699c | Ilias Tsitsimpis | filtered_imgs = \ |
338 | f772699c | Ilias Tsitsimpis | [i for i in images if |
339 | f772699c | Ilias Tsitsimpis | i['id'].lower() == img_value.lower()]
|
340 | f772699c | Ilias Tsitsimpis | else:
|
341 | f772699c | Ilias Tsitsimpis | self.error("Unrecognized image type %s", img_type) |
342 | f772699c | Ilias Tsitsimpis | self.fail("Unrecognized image type") |
343 | f772699c | Ilias Tsitsimpis | |
344 | f772699c | Ilias Tsitsimpis | # Check if we found one
|
345 | f772699c | Ilias Tsitsimpis | if filtered_imgs:
|
346 | f772699c | Ilias Tsitsimpis | img = filtered_imgs[0]
|
347 | f772699c | Ilias Tsitsimpis | self.info("Will use %s with id %s", img['name'], img['id']) |
348 | f772699c | Ilias Tsitsimpis | return img
|
349 | f772699c | Ilias Tsitsimpis | |
350 | f772699c | Ilias Tsitsimpis | # We didn't found one
|
351 | f772699c | Ilias Tsitsimpis | err = "No matching image found"
|
352 | f772699c | Ilias Tsitsimpis | self.error(err)
|
353 | f772699c | Ilias Tsitsimpis | self.fail(err)
|
354 | f772699c | Ilias Tsitsimpis | |
355 | f772699c | Ilias Tsitsimpis | # ----------------------------------
|
356 | f772699c | Ilias Tsitsimpis | # Pithos
|
357 | 79a5c431 | Ilias Tsitsimpis | def _set_pithos_account(self, account): |
358 | f772699c | Ilias Tsitsimpis | """Set the Pithos account"""
|
359 | 79a5c431 | Ilias Tsitsimpis | assert account, "No pithos account was given" |
360 | 79a5c431 | Ilias Tsitsimpis | |
361 | f772699c | Ilias Tsitsimpis | self.info("Setting Pithos account to %s", account) |
362 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos.account = account
|
363 | 79a5c431 | Ilias Tsitsimpis | |
364 | f772699c | Ilias Tsitsimpis | def _set_pithos_container(self, container): |
365 | f772699c | Ilias Tsitsimpis | """Set the Pithos container"""
|
366 | f772699c | Ilias Tsitsimpis | assert container, "No pithos container was given" |
367 | f772699c | Ilias Tsitsimpis | |
368 | f772699c | Ilias Tsitsimpis | self.info("Setting Pithos container to %s", container) |
369 | f772699c | Ilias Tsitsimpis | self.clients.pithos.container = container
|
370 | f772699c | Ilias Tsitsimpis | |
371 | 79a5c431 | Ilias Tsitsimpis | def _get_list_of_containers(self, account=None): |
372 | 79a5c431 | Ilias Tsitsimpis | """Get list of containers"""
|
373 | 79a5c431 | Ilias Tsitsimpis | if account is not None: |
374 | 79a5c431 | Ilias Tsitsimpis | self._set_pithos_account(account)
|
375 | 79a5c431 | Ilias Tsitsimpis | self.info("Getting list of containers") |
376 | 79a5c431 | Ilias Tsitsimpis | return self.clients.pithos.list_containers() |
377 | 79a5c431 | Ilias Tsitsimpis | |
378 | 79a5c431 | Ilias Tsitsimpis | def _create_pithos_container(self, container): |
379 | 79a5c431 | Ilias Tsitsimpis | """Create a pithos container
|
380 | 79a5c431 | Ilias Tsitsimpis |
|
381 | 79a5c431 | Ilias Tsitsimpis | If the container exists, nothing will happen
|
382 | 79a5c431 | Ilias Tsitsimpis |
|
383 | 79a5c431 | Ilias Tsitsimpis | """
|
384 | 79a5c431 | Ilias Tsitsimpis | assert container, "No pithos container was given" |
385 | 79a5c431 | Ilias Tsitsimpis | |
386 | 79a5c431 | Ilias Tsitsimpis | self.info("Creating pithos container %s", container) |
387 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos.container = container
|
388 | 79a5c431 | Ilias Tsitsimpis | self.clients.pithos.container_put()
|
389 | 79a5c431 | Ilias Tsitsimpis | |
390 | 4c52d5bf | Ilias Tsitsimpis | |
391 | 4c52d5bf | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
392 | 12ef696f | Ilias Tsitsimpis | # Initialize Burnin
|
393 | 12ef696f | Ilias Tsitsimpis | def initialize(opts, testsuites): |
394 | 12ef696f | Ilias Tsitsimpis | """Initalize burnin
|
395 | 12ef696f | Ilias Tsitsimpis |
|
396 | 12ef696f | Ilias Tsitsimpis | Initialize our logger and burnin state
|
397 | 12ef696f | Ilias Tsitsimpis |
|
398 | 12ef696f | Ilias Tsitsimpis | """
|
399 | 12ef696f | Ilias Tsitsimpis | # Initialize logger
|
400 | 12ef696f | Ilias Tsitsimpis | global logger # Using global statement. pylint: disable-msg=C0103,W0603 |
401 | 12ef696f | Ilias Tsitsimpis | logger = Log(opts.log_folder, verbose=opts.verbose, |
402 | 0c1833c8 | Ilias Tsitsimpis | use_colors=opts.use_colors, in_parallel=False,
|
403 | 0c1833c8 | Ilias Tsitsimpis | quiet=opts.quiet) |
404 | 12ef696f | Ilias Tsitsimpis | |
405 | 12ef696f | Ilias Tsitsimpis | # Initialize clients
|
406 | 12ef696f | Ilias Tsitsimpis | Clients.auth_url = opts.auth_url |
407 | 12ef696f | Ilias Tsitsimpis | Clients.token = opts.token |
408 | 12ef696f | Ilias Tsitsimpis | |
409 | 12ef696f | Ilias Tsitsimpis | # Pass the rest options to BurninTests
|
410 | 79a5c431 | Ilias Tsitsimpis | BurninTests.use_ipv6 = opts.use_ipv6 |
411 | 79a5c431 | Ilias Tsitsimpis | BurninTests.action_timeout = opts.action_timeout |
412 | 79a5c431 | Ilias Tsitsimpis | BurninTests.action_warning = opts.action_warning |
413 | 79a5c431 | Ilias Tsitsimpis | BurninTests.query_interval = opts.query_interval |
414 | f772699c | Ilias Tsitsimpis | BurninTests.system_user = opts.system_user |
415 | 79a5c431 | Ilias Tsitsimpis | BurninTests.run_id = SNF_TEST_PREFIX + \ |
416 | 79a5c431 | Ilias Tsitsimpis | datetime.datetime.strftime(datetime.datetime.now(), "%Y%m%d%H%M%S")
|
417 | 12ef696f | Ilias Tsitsimpis | |
418 | 12ef696f | Ilias Tsitsimpis | # Choose tests to run
|
419 | 12ef696f | Ilias Tsitsimpis | if opts.tests != "all": |
420 | 12ef696f | Ilias Tsitsimpis | testsuites = opts.tests |
421 | 12ef696f | Ilias Tsitsimpis | if opts.exclude_tests is not None: |
422 | 12ef696f | Ilias Tsitsimpis | testsuites = [tsuite for tsuite in testsuites |
423 | 12ef696f | Ilias Tsitsimpis | if tsuite not in opts.exclude_tests] |
424 | 12ef696f | Ilias Tsitsimpis | |
425 | 12ef696f | Ilias Tsitsimpis | return testsuites
|
426 | 12ef696f | Ilias Tsitsimpis | |
427 | 12ef696f | Ilias Tsitsimpis | |
428 | 12ef696f | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
429 | 12ef696f | Ilias Tsitsimpis | # Run Burnin
|
430 | 0c1833c8 | Ilias Tsitsimpis | def run(testsuites, failfast=False, final_report=False): |
431 | 12ef696f | Ilias Tsitsimpis | """Run burnin testsuites"""
|
432 | 12ef696f | Ilias Tsitsimpis | global logger # Using global. pylint: disable-msg=C0103,W0603,W0602 |
433 | 12ef696f | Ilias Tsitsimpis | |
434 | 12ef696f | Ilias Tsitsimpis | success = True
|
435 | 12ef696f | Ilias Tsitsimpis | for tcase in testsuites: |
436 | 12ef696f | Ilias Tsitsimpis | tsuite = unittest.TestLoader().loadTestsFromTestCase(tcase) |
437 | 12ef696f | Ilias Tsitsimpis | results = tsuite.run(BurninTestResult()) |
438 | fe15cd00 | Ilias Tsitsimpis | |
439 | fe15cd00 | Ilias Tsitsimpis | was_success = was_successful(tcase.__name__, results.wasSuccessful()) |
440 | fe15cd00 | Ilias Tsitsimpis | success = success and was_success
|
441 | 0c1833c8 | Ilias Tsitsimpis | if failfast and not success: |
442 | 0c1833c8 | Ilias Tsitsimpis | break
|
443 | 12ef696f | Ilias Tsitsimpis | |
444 | 0c1833c8 | Ilias Tsitsimpis | # Are we going to print final report?
|
445 | 0c1833c8 | Ilias Tsitsimpis | if final_report:
|
446 | 0c1833c8 | Ilias Tsitsimpis | logger.print_logfile_to_stdout() |
447 | 12ef696f | Ilias Tsitsimpis | # Clean up our logger
|
448 | 12ef696f | Ilias Tsitsimpis | del(logger)
|
449 | 12ef696f | Ilias Tsitsimpis | |
450 | 12ef696f | Ilias Tsitsimpis | # Return
|
451 | 12ef696f | Ilias Tsitsimpis | return 0 if success else 1 |
452 | 12ef696f | Ilias Tsitsimpis | |
453 | 12ef696f | Ilias Tsitsimpis | |
454 | 12ef696f | Ilias Tsitsimpis | # --------------------------------------------------------------------
|
455 | 4c52d5bf | Ilias Tsitsimpis | # Helper functions
|
456 | 12ef696f | Ilias Tsitsimpis | def was_successful(tsuite, success): |
457 | 4c52d5bf | Ilias Tsitsimpis | """Handle whether a testsuite was succesful or not"""
|
458 | 4c52d5bf | Ilias Tsitsimpis | if success:
|
459 | 4c52d5bf | Ilias Tsitsimpis | logger.testsuite_success(tsuite) |
460 | 12ef696f | Ilias Tsitsimpis | return True |
461 | 4c52d5bf | Ilias Tsitsimpis | else:
|
462 | 4c52d5bf | Ilias Tsitsimpis | logger.testsuite_failure(tsuite) |
463 | 12ef696f | Ilias Tsitsimpis | return False |
464 | f772699c | Ilias Tsitsimpis | |
465 | f772699c | Ilias Tsitsimpis | |
466 | f772699c | Ilias Tsitsimpis | def parse_typed_option(value): |
467 | f772699c | Ilias Tsitsimpis | """Parse typed options (flavors and images)
|
468 | f772699c | Ilias Tsitsimpis |
|
469 | f772699c | Ilias Tsitsimpis | The options are in the form 'id:123-345' or 'name:^Debian Base$'
|
470 | f772699c | Ilias Tsitsimpis |
|
471 | f772699c | Ilias Tsitsimpis | """
|
472 | f772699c | Ilias Tsitsimpis | try:
|
473 | f772699c | Ilias Tsitsimpis | [type_, val] = value.strip().split(':')
|
474 | f772699c | Ilias Tsitsimpis | if type_ not in ["id", "name"]: |
475 | f772699c | Ilias Tsitsimpis | raise ValueError |
476 | f772699c | Ilias Tsitsimpis | return type_, val
|
477 | f772699c | Ilias Tsitsimpis | except ValueError: |
478 | f772699c | Ilias Tsitsimpis | return None |
479 | d11c80c0 | Ilias Tsitsimpis | |
480 | d11c80c0 | Ilias Tsitsimpis | |
481 | d11c80c0 | Ilias Tsitsimpis | class Proper(object): |
482 | d11c80c0 | Ilias Tsitsimpis | """A descriptor used by tests implementing the TestCase class
|
483 | d11c80c0 | Ilias Tsitsimpis |
|
484 | d11c80c0 | Ilias Tsitsimpis | Since each instance of the TestCase will only be used to run a single
|
485 | d11c80c0 | Ilias Tsitsimpis | test method (a new fixture is created for each test) the attributes can
|
486 | d11c80c0 | Ilias Tsitsimpis | not be saved in the class instances. Instead we use descriptors.
|
487 | d11c80c0 | Ilias Tsitsimpis |
|
488 | d11c80c0 | Ilias Tsitsimpis | """
|
489 | d11c80c0 | Ilias Tsitsimpis | def __init__(self, value=None): |
490 | d11c80c0 | Ilias Tsitsimpis | self.val = value
|
491 | d11c80c0 | Ilias Tsitsimpis | |
492 | d11c80c0 | Ilias Tsitsimpis | def __get__(self, obj, objtype=None): |
493 | d11c80c0 | Ilias Tsitsimpis | return self.val |
494 | d11c80c0 | Ilias Tsitsimpis | |
495 | d11c80c0 | Ilias Tsitsimpis | def __set__(self, obj, value): |
496 | d11c80c0 | Ilias Tsitsimpis | self.val = value |