Statistics
| Branch: | Tag: | Revision:

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