Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin.py @ bcb7c357

History | View | Annotate | Download (78.5 kB)

1 65462ca9 John Giannelos
#!/usr/bin/env python
2 5a140b23 Vangelis Koukis
3 5a140b23 Vangelis Koukis
# Copyright 2011 GRNET S.A. All rights reserved.
4 5a140b23 Vangelis Koukis
#
5 5a140b23 Vangelis Koukis
# Redistribution and use in source and binary forms, with or
6 5a140b23 Vangelis Koukis
# without modification, are permitted provided that the following
7 5a140b23 Vangelis Koukis
# conditions are met:
8 5a140b23 Vangelis Koukis
#
9 5a140b23 Vangelis Koukis
#   1. Redistributions of source code must retain the above
10 5a140b23 Vangelis Koukis
#      copyright notice, this list of conditions and the following
11 5a140b23 Vangelis Koukis
#      disclaimer.
12 5a140b23 Vangelis Koukis
#
13 5a140b23 Vangelis Koukis
#   2. Redistributions in binary form must reproduce the above
14 5a140b23 Vangelis Koukis
#      copyright notice, this list of conditions and the following
15 5a140b23 Vangelis Koukis
#      disclaimer in the documentation and/or other materials
16 5a140b23 Vangelis Koukis
#      provided with the distribution.
17 5a140b23 Vangelis Koukis
#
18 5a140b23 Vangelis Koukis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 5a140b23 Vangelis Koukis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 5a140b23 Vangelis Koukis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 5a140b23 Vangelis Koukis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 5a140b23 Vangelis Koukis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 5a140b23 Vangelis Koukis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 5a140b23 Vangelis Koukis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 5a140b23 Vangelis Koukis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 5a140b23 Vangelis Koukis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 5a140b23 Vangelis Koukis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 5a140b23 Vangelis Koukis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 5a140b23 Vangelis Koukis
# POSSIBILITY OF SUCH DAMAGE.
30 5a140b23 Vangelis Koukis
#
31 5a140b23 Vangelis Koukis
# The views and conclusions contained in the software and
32 5a140b23 Vangelis Koukis
# documentation are those of the authors and should not be
33 5a140b23 Vangelis Koukis
# interpreted as representing official policies, either expressed
34 5a140b23 Vangelis Koukis
# or implied, of GRNET S.A.
35 5a140b23 Vangelis Koukis
36 5a140b23 Vangelis Koukis
"""Perform integration testing on a running Synnefo deployment"""
37 5a140b23 Vangelis Koukis
38 6e168615 Ilias Tsitsimpis
#import __main__
39 5a140b23 Vangelis Koukis
import datetime
40 5a140b23 Vangelis Koukis
import inspect
41 5a140b23 Vangelis Koukis
import logging
42 5a140b23 Vangelis Koukis
import os
43 11779b6c Ilias Tsitsimpis
import os.path
44 5a140b23 Vangelis Koukis
import paramiko
45 21bbbc9b Vangelis Koukis
import prctl
46 5a140b23 Vangelis Koukis
import subprocess
47 21bbbc9b Vangelis Koukis
import signal
48 5a140b23 Vangelis Koukis
import socket
49 5a140b23 Vangelis Koukis
import sys
50 5a140b23 Vangelis Koukis
import time
51 11779b6c Ilias Tsitsimpis
import tempfile
52 9659e075 John Giannelos
from base64 import b64encode
53 5a140b23 Vangelis Koukis
from IPy import IP
54 21bbbc9b Vangelis Koukis
from multiprocessing import Process, Queue
55 11779b6c Ilias Tsitsimpis
from random import choice, randint
56 22efe1fe John Giannelos
from optparse import OptionParser, OptionValueError
57 21bbbc9b Vangelis Koukis
58 96da37c8 John Giannelos
from kamaki.clients.compute import ComputeClient
59 96da37c8 John Giannelos
from kamaki.clients.cyclades import CycladesClient
60 946da8b6 John Giannelos
from kamaki.clients.image import ImageClient
61 11779b6c Ilias Tsitsimpis
from kamaki.clients.pithos import PithosClient
62 bacb7c87 Ilias Tsitsimpis
from kamaki.clients.astakos import AstakosClient
63 21dcb666 John Giannelos
from kamaki.clients import ClientError
64 96da37c8 John Giannelos
65 bc14ba88 Vangelis Koukis
from vncauthproxy.d3des import generate_response as d3des_generate_response
66 5a140b23 Vangelis Koukis
67 5a140b23 Vangelis Koukis
# Use backported unittest functionality if Python < 2.7
68 5a140b23 Vangelis Koukis
try:
69 5a140b23 Vangelis Koukis
    import unittest2 as unittest
70 5a140b23 Vangelis Koukis
except ImportError:
71 bc14ba88 Vangelis Koukis
    if sys.version_info < (2, 7):
72 bc14ba88 Vangelis Koukis
        raise Exception("The unittest2 package is required for Python < 2.7")
73 5a140b23 Vangelis Koukis
    import unittest
74 5a140b23 Vangelis Koukis
75 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
76 6e168615 Ilias Tsitsimpis
# Global Variables
77 6e168615 Ilias Tsitsimpis
API = None
78 6e168615 Ilias Tsitsimpis
TOKEN = None
79 6e168615 Ilias Tsitsimpis
PLANKTON = None
80 6e168615 Ilias Tsitsimpis
PLANKTON_USER = None
81 11779b6c Ilias Tsitsimpis
PITHOS = None
82 bacb7c87 Ilias Tsitsimpis
ASTAKOS = None
83 6e168615 Ilias Tsitsimpis
NO_IPV6 = None
84 6e168615 Ilias Tsitsimpis
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
85 6e168615 Ilias Tsitsimpis
NOFAILFAST = None
86 6e168615 Ilias Tsitsimpis
VERBOSE = None
87 6e168615 Ilias Tsitsimpis
88 6e168615 Ilias Tsitsimpis
# A unique id identifying this test run
89 6e168615 Ilias Tsitsimpis
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
90 6e168615 Ilias Tsitsimpis
                                         "%Y%m%d%H%M%S")
91 6e168615 Ilias Tsitsimpis
SNF_TEST_PREFIX = "snf-test-"
92 6e168615 Ilias Tsitsimpis
93 6e168615 Ilias Tsitsimpis
red = '\x1b[31m'
94 6e168615 Ilias Tsitsimpis
yellow = '\x1b[33m'
95 6e168615 Ilias Tsitsimpis
green = '\x1b[32m'
96 6e168615 Ilias Tsitsimpis
normal = '\x1b[0m'
97 6e168615 Ilias Tsitsimpis
98 5a140b23 Vangelis Koukis
99 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
100 2a410f76 Ilias Tsitsimpis
# Global functions
101 2a410f76 Ilias Tsitsimpis
def _ssh_execute(hostip, username, password, command):
102 2a410f76 Ilias Tsitsimpis
    """Execute a command via ssh"""
103 2a410f76 Ilias Tsitsimpis
    ssh = paramiko.SSHClient()
104 2a410f76 Ilias Tsitsimpis
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
105 2a410f76 Ilias Tsitsimpis
    try:
106 2a410f76 Ilias Tsitsimpis
        ssh.connect(hostip, username=username, password=password)
107 2a410f76 Ilias Tsitsimpis
    except socket.error:
108 2a410f76 Ilias Tsitsimpis
        raise AssertionError
109 2a410f76 Ilias Tsitsimpis
    try:
110 2a410f76 Ilias Tsitsimpis
        stdin, stdout, stderr = ssh.exec_command(command)
111 2a410f76 Ilias Tsitsimpis
    except paramiko.SSHException:
112 2a410f76 Ilias Tsitsimpis
        raise AssertionError
113 2a410f76 Ilias Tsitsimpis
    status = stdout.channel.recv_exit_status()
114 2a410f76 Ilias Tsitsimpis
    output = stdout.readlines()
115 2a410f76 Ilias Tsitsimpis
    ssh.close()
116 2a410f76 Ilias Tsitsimpis
    return output, status
117 2a410f76 Ilias Tsitsimpis
118 2a410f76 Ilias Tsitsimpis
119 bacb7c87 Ilias Tsitsimpis
def _get_user_id():
120 bacb7c87 Ilias Tsitsimpis
    """Authenticate to astakos and get unique users id"""
121 bacb7c87 Ilias Tsitsimpis
    astakos = AstakosClient(ASTAKOS, TOKEN)
122 965b25af Ilias Tsitsimpis
    authenticate = astakos.authenticate()
123 965b25af Ilias Tsitsimpis
    if 'uuid' in authenticate:
124 965b25af Ilias Tsitsimpis
        return authenticate['uuid']
125 965b25af Ilias Tsitsimpis
    else:
126 965b25af Ilias Tsitsimpis
        return authenticate['uniq']
127 bacb7c87 Ilias Tsitsimpis
128 bacb7c87 Ilias Tsitsimpis
129 2a410f76 Ilias Tsitsimpis
# --------------------------------------------------------------------
130 6e168615 Ilias Tsitsimpis
# BurninTestReulst class
131 66eba2cf John Giannelos
class BurninTestResult(unittest.TextTestResult):
132 66eba2cf John Giannelos
    def addSuccess(self, test):
133 66eba2cf John Giannelos
        super(BurninTestResult, self).addSuccess(test)
134 66eba2cf John Giannelos
        if self.showAll:
135 3e4c5c32 John Giannelos
            if hasattr(test, 'result_dict'):
136 66eba2cf John Giannelos
                run_details = test.result_dict
137 66eba2cf John Giannelos
138 66eba2cf John Giannelos
                self.stream.write("\n")
139 66eba2cf John Giannelos
                for i in run_details:
140 66eba2cf John Giannelos
                    self.stream.write("%s : %s \n" % (i, run_details[i]))
141 66eba2cf John Giannelos
                self.stream.write("\n")
142 66eba2cf John Giannelos
143 66eba2cf John Giannelos
        elif self.dots:
144 66eba2cf John Giannelos
            self.stream.write('.')
145 6e168615 Ilias Tsitsimpis
            self.stream.flush()
146 6e168615 Ilias Tsitsimpis
147 66eba2cf John Giannelos
    def addError(self, test, err):
148 66eba2cf John Giannelos
        super(BurninTestResult, self).addError(test, err)
149 66eba2cf John Giannelos
        if self.showAll:
150 66eba2cf John Giannelos
            self.stream.writeln("ERROR")
151 3e4c5c32 John Giannelos
            if hasattr(test, 'result_dict'):
152 3e4c5c32 John Giannelos
                run_details = test.result_dict
153 66eba2cf John Giannelos
154 3e4c5c32 John Giannelos
                self.stream.write("\n")
155 3e4c5c32 John Giannelos
                for i in run_details:
156 3e4c5c32 John Giannelos
                    self.stream.write("%s : %s \n" % (i, run_details[i]))
157 3e4c5c32 John Giannelos
                self.stream.write("\n")
158 66eba2cf John Giannelos
159 66eba2cf John Giannelos
        elif self.dots:
160 66eba2cf John Giannelos
            self.stream.write('E')
161 66eba2cf John Giannelos
            self.stream.flush()
162 66eba2cf John Giannelos
163 66eba2cf John Giannelos
    def addFailure(self, test, err):
164 66eba2cf John Giannelos
        super(BurninTestResult, self).addFailure(test, err)
165 66eba2cf John Giannelos
        if self.showAll:
166 66eba2cf John Giannelos
            self.stream.writeln("FAIL")
167 3e4c5c32 John Giannelos
            if hasattr(test, 'result_dict'):
168 3e4c5c32 John Giannelos
                run_details = test.result_dict
169 66eba2cf John Giannelos
170 3e4c5c32 John Giannelos
                self.stream.write("\n")
171 3e4c5c32 John Giannelos
                for i in run_details:
172 3e4c5c32 John Giannelos
                    self.stream.write("%s : %s \n" % (i, run_details[i]))
173 3e4c5c32 John Giannelos
                self.stream.write("\n")
174 66eba2cf John Giannelos
175 66eba2cf John Giannelos
        elif self.dots:
176 66eba2cf John Giannelos
            self.stream.write('F')
177 66eba2cf John Giannelos
            self.stream.flush()
178 66eba2cf John Giannelos
179 66eba2cf John Giannelos
180 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
181 6e168615 Ilias Tsitsimpis
# Format Results
182 746540cd John Giannelos
class burninFormatter(logging.Formatter):
183 746540cd John Giannelos
    err_fmt = red + "ERROR: %(msg)s" + normal
184 9b013c3a John Giannelos
    dbg_fmt = green + "* %(msg)s" + normal
185 746540cd John Giannelos
    info_fmt = "%(msg)s"
186 746540cd John Giannelos
187 746540cd John Giannelos
    def __init__(self, fmt="%(levelno)s: %(msg)s"):
188 746540cd John Giannelos
        logging.Formatter.__init__(self, fmt)
189 746540cd John Giannelos
190 746540cd John Giannelos
    def format(self, record):
191 746540cd John Giannelos
        format_orig = self._fmt
192 746540cd John Giannelos
        # Replace the original format with one customized by logging level
193 746540cd John Giannelos
        if record.levelno == 10:    # DEBUG
194 746540cd John Giannelos
            self._fmt = burninFormatter.dbg_fmt
195 746540cd John Giannelos
        elif record.levelno == 20:  # INFO
196 746540cd John Giannelos
            self._fmt = burninFormatter.info_fmt
197 746540cd John Giannelos
        elif record.levelno == 40:  # ERROR
198 746540cd John Giannelos
            self._fmt = burninFormatter.err_fmt
199 746540cd John Giannelos
        result = logging.Formatter.format(self, record)
200 746540cd John Giannelos
        self._fmt = format_orig
201 746540cd John Giannelos
        return result
202 746540cd John Giannelos
203 00f87624 Vangelis Koukis
log = logging.getLogger("burnin")
204 746540cd John Giannelos
log.setLevel(logging.DEBUG)
205 746540cd John Giannelos
handler = logging.StreamHandler()
206 746540cd John Giannelos
handler.setFormatter(burninFormatter())
207 746540cd John Giannelos
log.addHandler(handler)
208 5a140b23 Vangelis Koukis
209 2bcfb712 John Giannelos
210 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
211 6e168615 Ilias Tsitsimpis
# UnauthorizedTestCase class
212 5a140b23 Vangelis Koukis
class UnauthorizedTestCase(unittest.TestCase):
213 6e168615 Ilias Tsitsimpis
    """Test unauthorized access"""
214 66eba2cf John Giannelos
    @classmethod
215 66eba2cf John Giannelos
    def setUpClass(cls):
216 66eba2cf John Giannelos
        cls.result_dict = dict()
217 66eba2cf John Giannelos
218 5a140b23 Vangelis Koukis
    def test_unauthorized_access(self):
219 5a140b23 Vangelis Koukis
        """Test access without a valid token fails"""
220 81e8cbf6 John Giannelos
        log.info("Authentication test")
221 1c636ad6 John Giannelos
        falseToken = '12345'
222 2bcfb712 John Giannelos
        c = ComputeClient(API, falseToken)
223 1c636ad6 John Giannelos
224 5a140b23 Vangelis Koukis
        with self.assertRaises(ClientError) as cm:
225 5a140b23 Vangelis Koukis
            c.list_servers()
226 21dcb666 John Giannelos
            self.assertEqual(cm.exception.status, 401)
227 5a140b23 Vangelis Koukis
228 5a140b23 Vangelis Koukis
229 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
230 95a87099 Ilias Tsitsimpis
# This class gest replicated into Images TestCases dynamically
231 5a140b23 Vangelis Koukis
class ImagesTestCase(unittest.TestCase):
232 5a140b23 Vangelis Koukis
    """Test image lists for consistency"""
233 5a140b23 Vangelis Koukis
    @classmethod
234 5a140b23 Vangelis Koukis
    def setUpClass(cls):
235 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of images"""
236 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of images")
237 846980fe John Giannelos
        cls.client = ComputeClient(API, TOKEN)
238 946da8b6 John Giannelos
        cls.plankton = ImageClient(PLANKTON, TOKEN)
239 946da8b6 John Giannelos
        cls.images = cls.plankton.list_public()
240 946da8b6 John Giannelos
        cls.dimages = cls.plankton.list_public(detail=True)
241 66eba2cf John Giannelos
        cls.result_dict = dict()
242 bacb7c87 Ilias Tsitsimpis
        # Get uniq user id
243 bacb7c87 Ilias Tsitsimpis
        cls.uuid = _get_user_id()
244 bacb7c87 Ilias Tsitsimpis
        log.info("Uniq user id = %s" % cls.uuid)
245 95a87099 Ilias Tsitsimpis
        # Create temp directory and store it inside our class
246 95a87099 Ilias Tsitsimpis
        # XXX: In my machine /tmp has not enough space
247 95a87099 Ilias Tsitsimpis
        #      so use current directory to be sure.
248 95a87099 Ilias Tsitsimpis
        cls.temp_dir = tempfile.mkdtemp(dir=os.getcwd())
249 95a87099 Ilias Tsitsimpis
        cls.temp_image_name = \
250 95a87099 Ilias Tsitsimpis
            SNF_TEST_PREFIX + cls.imageid + ".diskdump"
251 5a140b23 Vangelis Koukis
252 4d72f9ab Ilias Tsitsimpis
    @classmethod
253 4d72f9ab Ilias Tsitsimpis
    def tearDownClass(cls):
254 4d72f9ab Ilias Tsitsimpis
        """Remove local files"""
255 4d72f9ab Ilias Tsitsimpis
        try:
256 4d72f9ab Ilias Tsitsimpis
            temp_file = os.path.join(cls.temp_dir, cls.temp_image_name)
257 4d72f9ab Ilias Tsitsimpis
            os.unlink(temp_file)
258 4d72f9ab Ilias Tsitsimpis
        except:
259 4d72f9ab Ilias Tsitsimpis
            pass
260 4d72f9ab Ilias Tsitsimpis
        try:
261 4d72f9ab Ilias Tsitsimpis
            os.rmdir(cls.temp_dir)
262 4d72f9ab Ilias Tsitsimpis
        except:
263 4d72f9ab Ilias Tsitsimpis
            pass
264 4d72f9ab Ilias Tsitsimpis
265 5a140b23 Vangelis Koukis
    def test_001_list_images(self):
266 5a140b23 Vangelis Koukis
        """Test image list actually returns images"""
267 6207533f John Giannelos
        self.assertGreater(len(self.images), 0)
268 74ec726f John Giannelos
269 5a140b23 Vangelis Koukis
    def test_002_list_images_detailed(self):
270 5a140b23 Vangelis Koukis
        """Test detailed image list is the same length as list"""
271 6207533f John Giannelos
        self.assertEqual(len(self.dimages), len(self.images))
272 74ec726f John Giannelos
273 5a140b23 Vangelis Koukis
    def test_003_same_image_names(self):
274 5a140b23 Vangelis Koukis
        """Test detailed and simple image list contain same names"""
275 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.images))
276 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dimages))
277 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
278 5a140b23 Vangelis Koukis
279 5a140b23 Vangelis Koukis
    def test_004_unique_image_names(self):
280 946da8b6 John Giannelos
        """Test system images have unique names"""
281 946da8b6 John Giannelos
        sys_images = filter(lambda x: x['owner'] == PLANKTON_USER,
282 946da8b6 John Giannelos
                            self.dimages)
283 946da8b6 John Giannelos
        names = sorted(map(lambda x: x["name"], sys_images))
284 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
285 5a140b23 Vangelis Koukis
286 5a140b23 Vangelis Koukis
    def test_005_image_metadata(self):
287 5a140b23 Vangelis Koukis
        """Test every image has specific metadata defined"""
288 2e3b7dc8 John Giannelos
        keys = frozenset(["osfamily", "root_partition"])
289 846980fe John Giannelos
        details = self.client.list_images(detail=True)
290 846980fe John Giannelos
        for i in details:
291 bcb7c357 Ilias Tsitsimpis
            self.assertTrue(keys.issubset(i["metadata"].keys()))
292 5a140b23 Vangelis Koukis
293 95a87099 Ilias Tsitsimpis
    def test_006_download_image(self):
294 95a87099 Ilias Tsitsimpis
        """Download image from pithos+"""
295 95a87099 Ilias Tsitsimpis
        # Get image location
296 95a87099 Ilias Tsitsimpis
        image = filter(
297 95a87099 Ilias Tsitsimpis
            lambda x: x['id'] == self.imageid, self.dimages)[0]
298 95a87099 Ilias Tsitsimpis
        image_location = \
299 95a87099 Ilias Tsitsimpis
            image['location'].replace("://", " ").replace("/", " ").split()
300 95a87099 Ilias Tsitsimpis
        log.info("Download image, with owner %s\n\tcontainer %s, and name %s"
301 95a87099 Ilias Tsitsimpis
                 % (image_location[1], image_location[2], image_location[3]))
302 95a87099 Ilias Tsitsimpis
        pithos_client = PithosClient(PITHOS, TOKEN, image_location[1])
303 95a87099 Ilias Tsitsimpis
        pithos_client.container = image_location[2]
304 95a87099 Ilias Tsitsimpis
        temp_file = os.path.join(self.temp_dir, self.temp_image_name)
305 95a87099 Ilias Tsitsimpis
        with open(temp_file, "wb+") as f:
306 95a87099 Ilias Tsitsimpis
            pithos_client.download_object(image_location[3], f)
307 95a87099 Ilias Tsitsimpis
308 95a87099 Ilias Tsitsimpis
    def test_007_upload_image(self):
309 95a87099 Ilias Tsitsimpis
        """Upload and register image"""
310 95a87099 Ilias Tsitsimpis
        temp_file = os.path.join(self.temp_dir, self.temp_image_name)
311 95a87099 Ilias Tsitsimpis
        log.info("Upload image to pithos+")
312 95a87099 Ilias Tsitsimpis
        # Create container `images'
313 bacb7c87 Ilias Tsitsimpis
        pithos_client = PithosClient(PITHOS, TOKEN, self.uuid)
314 95a87099 Ilias Tsitsimpis
        pithos_client.container = "images"
315 95a87099 Ilias Tsitsimpis
        pithos_client.container_put()
316 95a87099 Ilias Tsitsimpis
        with open(temp_file, "rb+") as f:
317 95a87099 Ilias Tsitsimpis
            pithos_client.upload_object(self.temp_image_name, f)
318 95a87099 Ilias Tsitsimpis
        log.info("Register image to plankton")
319 bacb7c87 Ilias Tsitsimpis
        location = "pithos://" + self.uuid + \
320 95a87099 Ilias Tsitsimpis
            "/images/" + self.temp_image_name
321 95a87099 Ilias Tsitsimpis
        params = {'is_public': True}
322 95a87099 Ilias Tsitsimpis
        properties = {'OSFAMILY': "linux", 'ROOT_PARTITION': 1}
323 95a87099 Ilias Tsitsimpis
        self.plankton.register(self.temp_image_name, location,
324 95a87099 Ilias Tsitsimpis
                               params, properties)
325 4d72f9ab Ilias Tsitsimpis
        # Get image id
326 4d72f9ab Ilias Tsitsimpis
        details = self.plankton.list_public(detail=True)
327 4c9918f9 Ilias Tsitsimpis
        detail = filter(lambda x: x['location'] == location, details)
328 4d72f9ab Ilias Tsitsimpis
        self.assertEqual(len(detail), 1)
329 4d72f9ab Ilias Tsitsimpis
        cls = type(self)
330 4d72f9ab Ilias Tsitsimpis
        cls.temp_image_id = detail[0]['id']
331 4d72f9ab Ilias Tsitsimpis
        log.info("Image registered with id %s" % detail[0]['id'])
332 4d72f9ab Ilias Tsitsimpis
333 4d72f9ab Ilias Tsitsimpis
    def test_008_cleanup_image(self):
334 4d72f9ab Ilias Tsitsimpis
        """Cleanup image test"""
335 4d72f9ab Ilias Tsitsimpis
        log.info("Cleanup image test")
336 4d72f9ab Ilias Tsitsimpis
        # Remove image from pithos+
337 bacb7c87 Ilias Tsitsimpis
        pithos_client = PithosClient(PITHOS, TOKEN, self.uuid)
338 4d72f9ab Ilias Tsitsimpis
        pithos_client.container = "images"
339 4d72f9ab Ilias Tsitsimpis
        pithos_client.del_object(self.temp_image_name)
340 95a87099 Ilias Tsitsimpis
341 5a140b23 Vangelis Koukis
342 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
343 6e168615 Ilias Tsitsimpis
# FlavorsTestCase class
344 5a140b23 Vangelis Koukis
class FlavorsTestCase(unittest.TestCase):
345 5a140b23 Vangelis Koukis
    """Test flavor lists for consistency"""
346 5a140b23 Vangelis Koukis
    @classmethod
347 5a140b23 Vangelis Koukis
    def setUpClass(cls):
348 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of flavors"""
349 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of flavors")
350 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
351 5a140b23 Vangelis Koukis
        cls.flavors = cls.client.list_flavors()
352 5a140b23 Vangelis Koukis
        cls.dflavors = cls.client.list_flavors(detail=True)
353 66eba2cf John Giannelos
        cls.result_dict = dict()
354 5a140b23 Vangelis Koukis
355 5a140b23 Vangelis Koukis
    def test_001_list_flavors(self):
356 5a140b23 Vangelis Koukis
        """Test flavor list actually returns flavors"""
357 5a140b23 Vangelis Koukis
        self.assertGreater(len(self.flavors), 0)
358 5a140b23 Vangelis Koukis
359 5a140b23 Vangelis Koukis
    def test_002_list_flavors_detailed(self):
360 5a140b23 Vangelis Koukis
        """Test detailed flavor list is the same length as list"""
361 5a140b23 Vangelis Koukis
        self.assertEquals(len(self.dflavors), len(self.flavors))
362 5a140b23 Vangelis Koukis
363 5a140b23 Vangelis Koukis
    def test_003_same_flavor_names(self):
364 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
365 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
366 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dflavors))
367 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
368 5a140b23 Vangelis Koukis
369 5a140b23 Vangelis Koukis
    def test_004_unique_flavor_names(self):
370 5a140b23 Vangelis Koukis
        """Test flavors have unique names"""
371 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
372 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
373 5a140b23 Vangelis Koukis
374 5a140b23 Vangelis Koukis
    def test_005_well_formed_flavor_names(self):
375 5a140b23 Vangelis Koukis
        """Test flavors have names of the form CxxRyyDzz
376 5a140b23 Vangelis Koukis
        Where xx is vCPU count, yy is RAM in MiB, zz is Disk in GiB
377 5a140b23 Vangelis Koukis
        """
378 5a140b23 Vangelis Koukis
        for f in self.dflavors:
379 0bfeb27e Christos Stavrakakis
            flavor = (f["cpu"], f["ram"], f["disk"], f["SNF:disk_template"])
380 95b36b00 Christos Stavrakakis
            self.assertEqual("C%dR%dD%d%s" % flavor,
381 5a140b23 Vangelis Koukis
                             f["name"],
382 5a140b23 Vangelis Koukis
                             "Flavor %s does not match its specs." % f["name"])
383 5a140b23 Vangelis Koukis
384 5a140b23 Vangelis Koukis
385 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
386 6e168615 Ilias Tsitsimpis
# ServersTestCase class
387 5a140b23 Vangelis Koukis
class ServersTestCase(unittest.TestCase):
388 5a140b23 Vangelis Koukis
    """Test server lists for consistency"""
389 5a140b23 Vangelis Koukis
    @classmethod
390 5a140b23 Vangelis Koukis
    def setUpClass(cls):
391 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of servers"""
392 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of servers")
393 1c636ad6 John Giannelos
394 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
395 5a140b23 Vangelis Koukis
        cls.servers = cls.client.list_servers()
396 5a140b23 Vangelis Koukis
        cls.dservers = cls.client.list_servers(detail=True)
397 66eba2cf John Giannelos
        cls.result_dict = dict()
398 5a140b23 Vangelis Koukis
399 139d3a0b Ilias Tsitsimpis
    # def test_001_list_servers(self):
400 139d3a0b Ilias Tsitsimpis
    #     """Test server list actually returns servers"""
401 139d3a0b Ilias Tsitsimpis
    #     self.assertGreater(len(self.servers), 0)
402 5a140b23 Vangelis Koukis
403 5a140b23 Vangelis Koukis
    def test_002_list_servers_detailed(self):
404 5a140b23 Vangelis Koukis
        """Test detailed server list is the same length as list"""
405 5a140b23 Vangelis Koukis
        self.assertEqual(len(self.dservers), len(self.servers))
406 5a140b23 Vangelis Koukis
407 5a140b23 Vangelis Koukis
    def test_003_same_server_names(self):
408 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
409 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.servers))
410 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dservers))
411 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
412 5a140b23 Vangelis Koukis
413 5a140b23 Vangelis Koukis
414 11779b6c Ilias Tsitsimpis
# --------------------------------------------------------------------
415 11779b6c Ilias Tsitsimpis
# Pithos Test Cases
416 11779b6c Ilias Tsitsimpis
class PithosTestCase(unittest.TestCase):
417 11779b6c Ilias Tsitsimpis
    """Test pithos functionality"""
418 11779b6c Ilias Tsitsimpis
    @classmethod
419 11779b6c Ilias Tsitsimpis
    def setUpClass(cls):
420 11779b6c Ilias Tsitsimpis
        """Initialize kamaki, get list of containers"""
421 bacb7c87 Ilias Tsitsimpis
        # Get uniq user id
422 bacb7c87 Ilias Tsitsimpis
        cls.uuid = _get_user_id()
423 bacb7c87 Ilias Tsitsimpis
        log.info("Uniq user id = %s" % cls.uuid)
424 11779b6c Ilias Tsitsimpis
        log.info("Getting list of containers")
425 bacb7c87 Ilias Tsitsimpis
        cls.client = PithosClient(PITHOS, TOKEN, cls.uuid)
426 11779b6c Ilias Tsitsimpis
        cls.containers = cls.client.list_containers()
427 11779b6c Ilias Tsitsimpis
        cls.result_dict = dict()
428 11779b6c Ilias Tsitsimpis
429 11779b6c Ilias Tsitsimpis
    def test_001_list_containers(self):
430 11779b6c Ilias Tsitsimpis
        """Test container list actually returns containers"""
431 11779b6c Ilias Tsitsimpis
        self.assertGreater(len(self.containers), 0)
432 11779b6c Ilias Tsitsimpis
433 11779b6c Ilias Tsitsimpis
    def test_002_unique_containers(self):
434 11779b6c Ilias Tsitsimpis
        """Test if containers have unique names"""
435 11779b6c Ilias Tsitsimpis
        names = [n['name'] for n in self.containers]
436 11779b6c Ilias Tsitsimpis
        names = sorted(names)
437 11779b6c Ilias Tsitsimpis
        self.assertEqual(sorted(list(set(names))), names)
438 11779b6c Ilias Tsitsimpis
439 11779b6c Ilias Tsitsimpis
    def test_003_create_container(self):
440 11779b6c Ilias Tsitsimpis
        """Test create a container"""
441 11779b6c Ilias Tsitsimpis
        rand_num = randint(1000, 9999)
442 11779b6c Ilias Tsitsimpis
        rand_name = "%s%s" % (SNF_TEST_PREFIX, rand_num)
443 11779b6c Ilias Tsitsimpis
        names = [n['name'] for n in self.containers]
444 11779b6c Ilias Tsitsimpis
        while rand_name in names:
445 11779b6c Ilias Tsitsimpis
            rand_num = randint(1000, 9999)
446 11779b6c Ilias Tsitsimpis
            rand_name = "%s%s" % (SNF_TEST_PREFIX, rand_num)
447 11779b6c Ilias Tsitsimpis
        # Create container
448 11779b6c Ilias Tsitsimpis
        self.client.container = rand_name
449 11779b6c Ilias Tsitsimpis
        self.client.container_put()
450 11779b6c Ilias Tsitsimpis
        # Get list of containers
451 11779b6c Ilias Tsitsimpis
        new_containers = self.client.list_containers()
452 11779b6c Ilias Tsitsimpis
        new_container_names = [n['name'] for n in new_containers]
453 11779b6c Ilias Tsitsimpis
        self.assertIn(rand_name, new_container_names)
454 11779b6c Ilias Tsitsimpis
455 11779b6c Ilias Tsitsimpis
    def test_004_upload(self):
456 11779b6c Ilias Tsitsimpis
        """Test uploading something to pithos+"""
457 11779b6c Ilias Tsitsimpis
        # Create a tmp file
458 11779b6c Ilias Tsitsimpis
        with tempfile.TemporaryFile() as f:
459 11779b6c Ilias Tsitsimpis
            f.write("This is a temp file")
460 11779b6c Ilias Tsitsimpis
            f.seek(0, 0)
461 11779b6c Ilias Tsitsimpis
            # Where to save file
462 11779b6c Ilias Tsitsimpis
            self.client.upload_object("test.txt", f)
463 11779b6c Ilias Tsitsimpis
464 11779b6c Ilias Tsitsimpis
    def test_005_download(self):
465 11779b6c Ilias Tsitsimpis
        """Test download something from pithos+"""
466 11779b6c Ilias Tsitsimpis
        # Create tmp directory to save file
467 11779b6c Ilias Tsitsimpis
        tmp_dir = tempfile.mkdtemp()
468 11779b6c Ilias Tsitsimpis
        tmp_file = os.path.join(tmp_dir, "test.txt")
469 11779b6c Ilias Tsitsimpis
        with open(tmp_file, "wb+") as f:
470 11779b6c Ilias Tsitsimpis
            self.client.download_object("test.txt", f)
471 11779b6c Ilias Tsitsimpis
            # Read file
472 11779b6c Ilias Tsitsimpis
            f.seek(0, 0)
473 11779b6c Ilias Tsitsimpis
            content = f.read()
474 11779b6c Ilias Tsitsimpis
        # Remove files
475 11779b6c Ilias Tsitsimpis
        os.unlink(tmp_file)
476 11779b6c Ilias Tsitsimpis
        os.rmdir(tmp_dir)
477 11779b6c Ilias Tsitsimpis
        # Compare results
478 11779b6c Ilias Tsitsimpis
        self.assertEqual(content, "This is a temp file")
479 11779b6c Ilias Tsitsimpis
480 11779b6c Ilias Tsitsimpis
    def test_006_remove(self):
481 11779b6c Ilias Tsitsimpis
        """Test removing files and containers"""
482 11779b6c Ilias Tsitsimpis
        cont_name = self.client.container
483 11779b6c Ilias Tsitsimpis
        self.client.del_object("test.txt")
484 11779b6c Ilias Tsitsimpis
        self.client.purge_container()
485 11779b6c Ilias Tsitsimpis
        # List containers
486 11779b6c Ilias Tsitsimpis
        containers = self.client.list_containers()
487 11779b6c Ilias Tsitsimpis
        cont_names = [n['name'] for n in containers]
488 11779b6c Ilias Tsitsimpis
        self.assertNotIn(cont_name, cont_names)
489 11779b6c Ilias Tsitsimpis
490 11779b6c Ilias Tsitsimpis
491 11779b6c Ilias Tsitsimpis
# --------------------------------------------------------------------
492 5a140b23 Vangelis Koukis
# This class gets replicated into actual TestCases dynamically
493 5a140b23 Vangelis Koukis
class SpawnServerTestCase(unittest.TestCase):
494 5a140b23 Vangelis Koukis
    """Test scenario for server of the specified image"""
495 5a140b23 Vangelis Koukis
    @classmethod
496 5a140b23 Vangelis Koukis
    def setUpClass(cls):
497 5a140b23 Vangelis Koukis
        """Initialize a kamaki instance"""
498 6e168615 Ilias Tsitsimpis
        log.info("Spawning server for image `%s'" % cls.imagename)
499 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
500 567ffb85 John Giannelos
        cls.cyclades = CycladesClient(API, TOKEN)
501 66eba2cf John Giannelos
        cls.result_dict = dict()
502 5a140b23 Vangelis Koukis
503 5a140b23 Vangelis Koukis
    def _get_ipv4(self, server):
504 bc14ba88 Vangelis Koukis
        """Get the public IPv4 of a server from the detailed server info"""
505 1c636ad6 John Giannelos
506 bcb7c357 Ilias Tsitsimpis
        nics = server["attachments"]
507 2aaa1336 John Giannelos
508 e50133da John Giannelos
        for nic in nics:
509 e50133da John Giannelos
            net_id = nic["network_id"]
510 6e168615 Ilias Tsitsimpis
            if self.cyclades.get_network_details(net_id)["public"]:
511 e50133da John Giannelos
                public_addrs = nic["ipv4"]
512 6e168615 Ilias Tsitsimpis
513 6e168615 Ilias Tsitsimpis
        self.assertTrue(public_addrs is not None)
514 2aaa1336 John Giannelos
515 e50133da John Giannelos
        return public_addrs
516 5a140b23 Vangelis Koukis
517 5a140b23 Vangelis Koukis
    def _get_ipv6(self, server):
518 bc14ba88 Vangelis Koukis
        """Get the public IPv6 of a server from the detailed server info"""
519 2aaa1336 John Giannelos
520 bcb7c357 Ilias Tsitsimpis
        nics = server["attachments"]
521 2aaa1336 John Giannelos
522 e50133da John Giannelos
        for nic in nics:
523 e50133da John Giannelos
            net_id = nic["network_id"]
524 6e168615 Ilias Tsitsimpis
            if self.cyclades.get_network_details(net_id)["public"]:
525 e50133da John Giannelos
                public_addrs = nic["ipv6"]
526 2aaa1336 John Giannelos
527 6e168615 Ilias Tsitsimpis
        self.assertTrue(public_addrs is not None)
528 2aaa1336 John Giannelos
529 6e168615 Ilias Tsitsimpis
        return public_addrs
530 5a140b23 Vangelis Koukis
531 6e168615 Ilias Tsitsimpis
    def _connect_loginname(self, os_value):
532 bc14ba88 Vangelis Koukis
        """Return the login name for connections based on the server OS"""
533 6e168615 Ilias Tsitsimpis
        if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
534 21bbbc9b Vangelis Koukis
            return "user"
535 6e168615 Ilias Tsitsimpis
        elif os_value in ("windows", "windows_alpha1"):
536 21bbbc9b Vangelis Koukis
            return "Administrator"
537 bc14ba88 Vangelis Koukis
        else:
538 21bbbc9b Vangelis Koukis
            return "root"
539 bc14ba88 Vangelis Koukis
540 bc14ba88 Vangelis Koukis
    def _verify_server_status(self, current_status, new_status):
541 bc14ba88 Vangelis Koukis
        """Verify a server has switched to a specified status"""
542 bc14ba88 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
543 21bbbc9b Vangelis Koukis
        if server["status"] not in (current_status, new_status):
544 21bbbc9b Vangelis Koukis
            return None  # Do not raise exception, return so the test fails
545 bc14ba88 Vangelis Koukis
        self.assertEquals(server["status"], new_status)
546 bc14ba88 Vangelis Koukis
547 bc14ba88 Vangelis Koukis
    def _get_connected_tcp_socket(self, family, host, port):
548 bc14ba88 Vangelis Koukis
        """Get a connected socket from the specified family to host:port"""
549 bc14ba88 Vangelis Koukis
        sock = None
550 bc14ba88 Vangelis Koukis
        for res in \
551 bc14ba88 Vangelis Koukis
            socket.getaddrinfo(host, port, family, socket.SOCK_STREAM, 0,
552 bc14ba88 Vangelis Koukis
                               socket.AI_PASSIVE):
553 bc14ba88 Vangelis Koukis
            af, socktype, proto, canonname, sa = res
554 bc14ba88 Vangelis Koukis
            try:
555 bc14ba88 Vangelis Koukis
                sock = socket.socket(af, socktype, proto)
556 6e168615 Ilias Tsitsimpis
            except socket.error:
557 bc14ba88 Vangelis Koukis
                sock = None
558 bc14ba88 Vangelis Koukis
                continue
559 bc14ba88 Vangelis Koukis
            try:
560 bc14ba88 Vangelis Koukis
                sock.connect(sa)
561 6e168615 Ilias Tsitsimpis
            except socket.error:
562 bc14ba88 Vangelis Koukis
                sock.close()
563 bc14ba88 Vangelis Koukis
                sock = None
564 bc14ba88 Vangelis Koukis
                continue
565 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(sock)
566 bc14ba88 Vangelis Koukis
        return sock
567 bc14ba88 Vangelis Koukis
568 bc14ba88 Vangelis Koukis
    def _ping_once(self, ipv6, ip):
569 bc14ba88 Vangelis Koukis
        """Test server responds to a single IPv4 or IPv6 ping"""
570 bc14ba88 Vangelis Koukis
        cmd = "ping%s -c 2 -w 3 %s" % ("6" if ipv6 else "", ip)
571 bc14ba88 Vangelis Koukis
        ping = subprocess.Popen(cmd, shell=True,
572 bc14ba88 Vangelis Koukis
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
573 bc14ba88 Vangelis Koukis
        (stdout, stderr) = ping.communicate()
574 bc14ba88 Vangelis Koukis
        ret = ping.wait()
575 bc14ba88 Vangelis Koukis
        self.assertEquals(ret, 0)
576 5a140b23 Vangelis Koukis
577 bc14ba88 Vangelis Koukis
    def _get_hostname_over_ssh(self, hostip, username, password):
578 2a410f76 Ilias Tsitsimpis
        lines, status = _ssh_execute(
579 2a410f76 Ilias Tsitsimpis
            hostip, username, password, "hostname")
580 bc14ba88 Vangelis Koukis
        self.assertEqual(len(lines), 1)
581 4fdd25ab Vangelis Koukis
        return lines[0]
582 bc14ba88 Vangelis Koukis
583 bc14ba88 Vangelis Koukis
    def _try_until_timeout_expires(self, warn_timeout, fail_timeout,
584 bc14ba88 Vangelis Koukis
                                   opmsg, callable, *args, **kwargs):
585 bc14ba88 Vangelis Koukis
        if warn_timeout == fail_timeout:
586 5a140b23 Vangelis Koukis
            warn_timeout = fail_timeout + 1
587 5a140b23 Vangelis Koukis
        warn_tmout = time.time() + warn_timeout
588 5a140b23 Vangelis Koukis
        fail_tmout = time.time() + fail_timeout
589 5a140b23 Vangelis Koukis
        while True:
590 4fdd25ab Vangelis Koukis
            self.assertLess(time.time(), fail_tmout,
591 21bbbc9b Vangelis Koukis
                            "operation `%s' timed out" % opmsg)
592 5a140b23 Vangelis Koukis
            if time.time() > warn_tmout:
593 4fdd25ab Vangelis Koukis
                log.warning("Server %d: `%s' operation `%s' not done yet",
594 4fdd25ab Vangelis Koukis
                            self.serverid, self.servername, opmsg)
595 bc14ba88 Vangelis Koukis
            try:
596 4fdd25ab Vangelis Koukis
                log.info("%s... " % opmsg)
597 bc14ba88 Vangelis Koukis
                return callable(*args, **kwargs)
598 bc14ba88 Vangelis Koukis
            except AssertionError:
599 bc14ba88 Vangelis Koukis
                pass
600 5a140b23 Vangelis Koukis
            time.sleep(self.query_interval)
601 5a140b23 Vangelis Koukis
602 bc14ba88 Vangelis Koukis
    def _insist_on_tcp_connection(self, family, host, port):
603 21bbbc9b Vangelis Koukis
        familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6",
604 21bbbc9b Vangelis Koukis
                     socket.AF_UNSPEC: "Unspecified-IPv4/6"}
605 bc14ba88 Vangelis Koukis
        msg = "connect over %s to %s:%s" % \
606 bc14ba88 Vangelis Koukis
              (familystr.get(family, "Unknown"), host, port)
607 bc14ba88 Vangelis Koukis
        sock = self._try_until_timeout_expires(
608 6e168615 Ilias Tsitsimpis
            self.action_timeout, self.action_timeout,
609 6e168615 Ilias Tsitsimpis
            msg, self._get_connected_tcp_socket,
610 6e168615 Ilias Tsitsimpis
            family, host, port)
611 bc14ba88 Vangelis Koukis
        return sock
612 bc14ba88 Vangelis Koukis
613 bc14ba88 Vangelis Koukis
    def _insist_on_status_transition(self, current_status, new_status,
614 6e168615 Ilias Tsitsimpis
                                     fail_timeout, warn_timeout=None):
615 4fdd25ab Vangelis Koukis
        msg = "Server %d: `%s', waiting for %s -> %s" % \
616 4fdd25ab Vangelis Koukis
              (self.serverid, self.servername, current_status, new_status)
617 bc14ba88 Vangelis Koukis
        if warn_timeout is None:
618 bc14ba88 Vangelis Koukis
            warn_timeout = fail_timeout
619 bc14ba88 Vangelis Koukis
        self._try_until_timeout_expires(warn_timeout, fail_timeout,
620 bc14ba88 Vangelis Koukis
                                        msg, self._verify_server_status,
621 bc14ba88 Vangelis Koukis
                                        current_status, new_status)
622 21bbbc9b Vangelis Koukis
        # Ensure the status is actually the expected one
623 21bbbc9b Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
624 21bbbc9b Vangelis Koukis
        self.assertEquals(server["status"], new_status)
625 bc14ba88 Vangelis Koukis
626 bc14ba88 Vangelis Koukis
    def _insist_on_ssh_hostname(self, hostip, username, password):
627 4fdd25ab Vangelis Koukis
        msg = "SSH to %s, as %s/%s" % (hostip, username, password)
628 bc14ba88 Vangelis Koukis
        hostname = self._try_until_timeout_expires(
629 6e168615 Ilias Tsitsimpis
            self.action_timeout, self.action_timeout,
630 6e168615 Ilias Tsitsimpis
            msg, self._get_hostname_over_ssh,
631 6e168615 Ilias Tsitsimpis
            hostip, username, password)
632 bc14ba88 Vangelis Koukis
633 bc14ba88 Vangelis Koukis
        # The hostname must be of the form 'prefix-id'
634 bc14ba88 Vangelis Koukis
        self.assertTrue(hostname.endswith("-%d\n" % self.serverid))
635 5a140b23 Vangelis Koukis
636 8252d64f John Giannelos
    def _check_file_through_ssh(self, hostip, username, password,
637 8252d64f John Giannelos
                                remotepath, content):
638 8252d64f John Giannelos
        msg = "Trying file injection through SSH to %s, as %s/%s" % \
639 8252d64f John Giannelos
            (hostip, username, password)
640 f97dce4d John Giannelos
        log.info(msg)
641 77054bf5 John Giannelos
        try:
642 77054bf5 John Giannelos
            ssh = paramiko.SSHClient()
643 77054bf5 John Giannelos
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
644 77054bf5 John Giannelos
            ssh.connect(hostip, username=username, password=password)
645 2a410f76 Ilias Tsitsimpis
            ssh.close()
646 77054bf5 John Giannelos
        except socket.error:
647 77054bf5 John Giannelos
            raise AssertionError
648 9659e075 John Giannelos
649 2bcfb712 John Giannelos
        transport = paramiko.Transport((hostip, 22))
650 2bcfb712 John Giannelos
        transport.connect(username=username, password=password)
651 2bcfb712 John Giannelos
652 2bcfb712 John Giannelos
        localpath = '/tmp/' + SNF_TEST_PREFIX + 'injection'
653 77054bf5 John Giannelos
        sftp = paramiko.SFTPClient.from_transport(transport)
654 8252d64f John Giannelos
        sftp.get(remotepath, localpath)
655 77054bf5 John Giannelos
        sftp.close()
656 77054bf5 John Giannelos
        transport.close()
657 77054bf5 John Giannelos
658 9659e075 John Giannelos
        f = open(localpath)
659 9659e075 John Giannelos
        remote_content = b64encode(f.read())
660 9659e075 John Giannelos
661 77054bf5 John Giannelos
        # Check if files are the same
662 65462ca9 John Giannelos
        return (remote_content == content)
663 77054bf5 John Giannelos
664 5a140b23 Vangelis Koukis
    def _skipIf(self, condition, msg):
665 5a140b23 Vangelis Koukis
        if condition:
666 5a140b23 Vangelis Koukis
            self.skipTest(msg)
667 5a140b23 Vangelis Koukis
668 5a140b23 Vangelis Koukis
    def test_001_submit_create_server(self):
669 5a140b23 Vangelis Koukis
        """Test submit create server request"""
670 f89d0238 John Giannelos
671 f89d0238 John Giannelos
        log.info("Submit new server request")
672 5a140b23 Vangelis Koukis
        server = self.client.create_server(self.servername, self.flavorid,
673 5a140b23 Vangelis Koukis
                                           self.imageid, self.personality)
674 9659e075 John Giannelos
675 81e8cbf6 John Giannelos
        log.info("Server id: " + str(server["id"]))
676 81e8cbf6 John Giannelos
        log.info("Server password: " + server["adminPass"])
677 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
678 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["flavor"], self.flavorid)
679 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["image"], self.imageid)
680 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
681 5a140b23 Vangelis Koukis
682 5a140b23 Vangelis Koukis
        # Update class attributes to reflect data on building server
683 5a140b23 Vangelis Koukis
        cls = type(self)
684 5a140b23 Vangelis Koukis
        cls.serverid = server["id"]
685 bc14ba88 Vangelis Koukis
        cls.username = None
686 5a140b23 Vangelis Koukis
        cls.passwd = server["adminPass"]
687 5a140b23 Vangelis Koukis
688 66eba2cf John Giannelos
        self.result_dict["Server ID"] = str(server["id"])
689 66eba2cf John Giannelos
        self.result_dict["Password"] = str(server["adminPass"])
690 66eba2cf John Giannelos
691 5a140b23 Vangelis Koukis
    def test_002a_server_is_building_in_list(self):
692 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in server list"""
693 f89d0238 John Giannelos
        log.info("Server in BUILD state in server list")
694 f89d0238 John Giannelos
695 66eba2cf John Giannelos
        self.result_dict.clear()
696 66eba2cf John Giannelos
697 5a140b23 Vangelis Koukis
        servers = self.client.list_servers(detail=True)
698 5a140b23 Vangelis Koukis
        servers = filter(lambda x: x["name"] == self.servername, servers)
699 2aaa1336 John Giannelos
700 5a140b23 Vangelis Koukis
        server = servers[0]
701 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
702 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["flavor"], self.flavorid)
703 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["image"], self.imageid)
704 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
705 5a140b23 Vangelis Koukis
706 5a140b23 Vangelis Koukis
    def test_002b_server_is_building_in_details(self):
707 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in details"""
708 f89d0238 John Giannelos
709 f89d0238 John Giannelos
        log.info("Server in BUILD state in details")
710 f89d0238 John Giannelos
711 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
712 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
713 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["flavor"], self.flavorid)
714 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(server["image"], self.imageid)
715 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
716 5a140b23 Vangelis Koukis
717 5a140b23 Vangelis Koukis
    def test_002c_set_server_metadata(self):
718 f89d0238 John Giannelos
719 f89d0238 John Giannelos
        log.info("Creating server metadata")
720 f89d0238 John Giannelos
721 5a140b23 Vangelis Koukis
        image = self.client.get_image_details(self.imageid)
722 bcb7c357 Ilias Tsitsimpis
        os_value = image["metadata"]["os"]
723 bcb7c357 Ilias Tsitsimpis
        users = image["metadata"].get("users", None)
724 6e168615 Ilias Tsitsimpis
        self.client.update_server_metadata(self.serverid, OS=os_value)
725 746540cd John Giannelos
726 e49bdb7c John Giannelos
        userlist = users.split()
727 81e8cbf6 John Giannelos
728 bc14ba88 Vangelis Koukis
        # Determine the username to use for future connections
729 bc14ba88 Vangelis Koukis
        # to this host
730 bc14ba88 Vangelis Koukis
        cls = type(self)
731 81e8cbf6 John Giannelos
732 81e8cbf6 John Giannelos
        if "root" in userlist:
733 81e8cbf6 John Giannelos
            cls.username = "root"
734 6e168615 Ilias Tsitsimpis
        elif users is None:
735 6e168615 Ilias Tsitsimpis
            cls.username = self._connect_loginname(os_value)
736 81e8cbf6 John Giannelos
        else:
737 81e8cbf6 John Giannelos
            cls.username = choice(userlist)
738 81e8cbf6 John Giannelos
739 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(cls.username)
740 5a140b23 Vangelis Koukis
741 5a140b23 Vangelis Koukis
    def test_002d_verify_server_metadata(self):
742 5a140b23 Vangelis Koukis
        """Test server metadata keys are set based on image metadata"""
743 f89d0238 John Giannelos
744 f89d0238 John Giannelos
        log.info("Verifying image metadata")
745 f89d0238 John Giannelos
746 5a140b23 Vangelis Koukis
        servermeta = self.client.get_server_metadata(self.serverid)
747 5a140b23 Vangelis Koukis
        imagemeta = self.client.get_image_metadata(self.imageid)
748 81e8cbf6 John Giannelos
749 99d41650 John Giannelos
        self.assertEqual(servermeta["OS"], imagemeta["os"])
750 5a140b23 Vangelis Koukis
751 5a140b23 Vangelis Koukis
    def test_003_server_becomes_active(self):
752 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE"""
753 f89d0238 John Giannelos
754 f89d0238 John Giannelos
        log.info("Waiting for server to become ACTIVE")
755 f89d0238 John Giannelos
756 6e168615 Ilias Tsitsimpis
        self._insist_on_status_transition(
757 6e168615 Ilias Tsitsimpis
            "BUILD", "ACTIVE", self.build_fail, self.build_warning)
758 5a140b23 Vangelis Koukis
759 f752215c John Giannelos
    def test_003a_get_server_oob_console(self):
760 f752215c John Giannelos
        """Test getting OOB server console over VNC
761 bc14ba88 Vangelis Koukis

762 f752215c John Giannelos
        Implementation of RFB protocol follows
763 f752215c John Giannelos
        http://www.realvnc.com/docs/rfbproto.pdf.
764 bc14ba88 Vangelis Koukis

765 f752215c John Giannelos
        """
766 f752215c John Giannelos
        console = self.cyclades.get_server_console(self.serverid)
767 f752215c John Giannelos
        self.assertEquals(console['type'], "vnc")
768 6e168615 Ilias Tsitsimpis
        sock = self._insist_on_tcp_connection(
769 6e168615 Ilias Tsitsimpis
            socket.AF_INET, console["host"], console["port"])
770 f752215c John Giannelos
771 f752215c John Giannelos
        # Step 1. ProtocolVersion message (par. 6.1.1)
772 f752215c John Giannelos
        version = sock.recv(1024)
773 f752215c John Giannelos
        self.assertEquals(version, 'RFB 003.008\n')
774 f752215c John Giannelos
        sock.send(version)
775 f752215c John Giannelos
776 f752215c John Giannelos
        # Step 2. Security (par 6.1.2): Only VNC Authentication supported
777 f752215c John Giannelos
        sec = sock.recv(1024)
778 f752215c John Giannelos
        self.assertEquals(list(sec), ['\x01', '\x02'])
779 f752215c John Giannelos
780 f752215c John Giannelos
        # Step 3. Request VNC Authentication (par 6.1.2)
781 f752215c John Giannelos
        sock.send('\x02')
782 f752215c John Giannelos
783 f752215c John Giannelos
        # Step 4. Receive Challenge (par 6.2.2)
784 f752215c John Giannelos
        challenge = sock.recv(1024)
785 f752215c John Giannelos
        self.assertEquals(len(challenge), 16)
786 f752215c John Giannelos
787 f752215c John Giannelos
        # Step 5. DES-Encrypt challenge, use password as key (par 6.2.2)
788 f752215c John Giannelos
        response = d3des_generate_response(
789 f752215c John Giannelos
            (console["password"] + '\0' * 8)[:8], challenge)
790 f752215c John Giannelos
        sock.send(response)
791 f752215c John Giannelos
792 f752215c John Giannelos
        # Step 6. SecurityResult (par 6.1.3)
793 f752215c John Giannelos
        result = sock.recv(4)
794 f752215c John Giannelos
        self.assertEquals(list(result), ['\x00', '\x00', '\x00', '\x00'])
795 f752215c John Giannelos
        sock.close()
796 8252d64f John Giannelos
797 5a140b23 Vangelis Koukis
    def test_004_server_has_ipv4(self):
798 5a140b23 Vangelis Koukis
        """Test active server has a valid IPv4 address"""
799 f89d0238 John Giannelos
800 81e8cbf6 John Giannelos
        log.info("Validate server's IPv4")
801 f89d0238 John Giannelos
802 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
803 5a140b23 Vangelis Koukis
        ipv4 = self._get_ipv4(server)
804 66eba2cf John Giannelos
805 66eba2cf John Giannelos
        self.result_dict.clear()
806 66eba2cf John Giannelos
        self.result_dict["IPv4"] = str(ipv4)
807 66eba2cf John Giannelos
808 5a140b23 Vangelis Koukis
        self.assertEquals(IP(ipv4).version(), 4)
809 5a140b23 Vangelis Koukis
810 65462ca9 John Giannelos
    def test_005_server_has_ipv6(self):
811 65462ca9 John Giannelos
        """Test active server has a valid IPv6 address"""
812 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
813 f89d0238 John Giannelos
814 81e8cbf6 John Giannelos
        log.info("Validate server's IPv6")
815 f89d0238 John Giannelos
816 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
817 65462ca9 John Giannelos
        ipv6 = self._get_ipv6(server)
818 66eba2cf John Giannelos
819 66eba2cf John Giannelos
        self.result_dict.clear()
820 66eba2cf John Giannelos
        self.result_dict["IPv6"] = str(ipv6)
821 66eba2cf John Giannelos
822 65462ca9 John Giannelos
        self.assertEquals(IP(ipv6).version(), 6)
823 5a140b23 Vangelis Koukis
824 daac4017 John Giannelos
    def test_006_server_responds_to_ping_IPv4(self):
825 daac4017 John Giannelos
        """Test server responds to ping on IPv4 address"""
826 daac4017 John Giannelos
827 daac4017 John Giannelos
        log.info("Testing if server responds to pings in IPv4")
828 66eba2cf John Giannelos
        self.result_dict.clear()
829 daac4017 John Giannelos
830 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
831 daac4017 John Giannelos
        ip = self._get_ipv4(server)
832 daac4017 John Giannelos
        self._try_until_timeout_expires(self.action_timeout,
833 daac4017 John Giannelos
                                        self.action_timeout,
834 daac4017 John Giannelos
                                        "PING IPv4 to %s" % ip,
835 daac4017 John Giannelos
                                        self._ping_once,
836 daac4017 John Giannelos
                                        False, ip)
837 daac4017 John Giannelos
838 daac4017 John Giannelos
    def test_007_server_responds_to_ping_IPv6(self):
839 daac4017 John Giannelos
        """Test server responds to ping on IPv6 address"""
840 daac4017 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
841 daac4017 John Giannelos
        log.info("Testing if server responds to pings in IPv6")
842 daac4017 John Giannelos
843 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
844 daac4017 John Giannelos
        ip = self._get_ipv6(server)
845 daac4017 John Giannelos
        self._try_until_timeout_expires(self.action_timeout,
846 daac4017 John Giannelos
                                        self.action_timeout,
847 daac4017 John Giannelos
                                        "PING IPv6 to %s" % ip,
848 daac4017 John Giannelos
                                        self._ping_once,
849 daac4017 John Giannelos
                                        True, ip)
850 5a140b23 Vangelis Koukis
851 5a140b23 Vangelis Koukis
    def test_008_submit_shutdown_request(self):
852 5a140b23 Vangelis Koukis
        """Test submit request to shutdown server"""
853 f89d0238 John Giannelos
854 f89d0238 John Giannelos
        log.info("Shutting down server")
855 f89d0238 John Giannelos
856 74193008 John Giannelos
        self.cyclades.shutdown_server(self.serverid)
857 5a140b23 Vangelis Koukis
858 5a140b23 Vangelis Koukis
    def test_009_server_becomes_stopped(self):
859 5a140b23 Vangelis Koukis
        """Test server becomes STOPPED"""
860 f89d0238 John Giannelos
861 f89d0238 John Giannelos
        log.info("Waiting until server becomes STOPPED")
862 6e168615 Ilias Tsitsimpis
        self._insist_on_status_transition(
863 6e168615 Ilias Tsitsimpis
            "ACTIVE", "STOPPED", self.action_timeout, self.action_timeout)
864 5a140b23 Vangelis Koukis
865 5a140b23 Vangelis Koukis
    def test_010_submit_start_request(self):
866 5a140b23 Vangelis Koukis
        """Test submit start server request"""
867 f89d0238 John Giannelos
868 f89d0238 John Giannelos
        log.info("Starting server")
869 f89d0238 John Giannelos
870 74193008 John Giannelos
        self.cyclades.start_server(self.serverid)
871 5a140b23 Vangelis Koukis
872 5a140b23 Vangelis Koukis
    def test_011_server_becomes_active(self):
873 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE again"""
874 f89d0238 John Giannelos
875 f89d0238 John Giannelos
        log.info("Waiting until server becomes ACTIVE")
876 6e168615 Ilias Tsitsimpis
        self._insist_on_status_transition(
877 6e168615 Ilias Tsitsimpis
            "STOPPED", "ACTIVE", self.action_timeout, self.action_timeout)
878 5a140b23 Vangelis Koukis
879 daac4017 John Giannelos
    def test_011a_server_responds_to_ping_IPv4(self):
880 daac4017 John Giannelos
        """Test server OS is actually up and running again"""
881 f89d0238 John Giannelos
882 daac4017 John Giannelos
        log.info("Testing if server is actually up and running")
883 f89d0238 John Giannelos
884 daac4017 John Giannelos
        self.test_006_server_responds_to_ping_IPv4()
885 5a140b23 Vangelis Koukis
886 daac4017 John Giannelos
    def test_012_ssh_to_server_IPv4(self):
887 daac4017 John Giannelos
        """Test SSH to server public IPv4 works, verify hostname"""
888 f89d0238 John Giannelos
889 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
890 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
891 daac4017 John Giannelos
        self._insist_on_ssh_hostname(self._get_ipv4(server),
892 daac4017 John Giannelos
                                     self.username, self.passwd)
893 5a140b23 Vangelis Koukis
894 daac4017 John Giannelos
    def test_013_ssh_to_server_IPv6(self):
895 daac4017 John Giannelos
        """Test SSH to server public IPv6 works, verify hostname"""
896 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
897 daac4017 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
898 946da8b6 John Giannelos
899 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
900 daac4017 John Giannelos
        self._insist_on_ssh_hostname(self._get_ipv6(server),
901 daac4017 John Giannelos
                                     self.username, self.passwd)
902 5a140b23 Vangelis Koukis
903 daac4017 John Giannelos
    def test_014_rdp_to_server_IPv4(self):
904 daac4017 John Giannelos
        "Test RDP connection to server public IPv4 works"""
905 daac4017 John Giannelos
        self._skipIf(not self.is_windows, "only valid for Windows servers")
906 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
907 daac4017 John Giannelos
        ipv4 = self._get_ipv4(server)
908 6e168615 Ilias Tsitsimpis
        sock = self._insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
909 5a140b23 Vangelis Koukis
910 daac4017 John Giannelos
        # No actual RDP processing done. We assume the RDP server is there
911 daac4017 John Giannelos
        # if the connection to the RDP port is successful.
912 daac4017 John Giannelos
        # FIXME: Use rdesktop, analyze exit code? see manpage [costasd]
913 daac4017 John Giannelos
        sock.close()
914 5a140b23 Vangelis Koukis
915 daac4017 John Giannelos
    def test_015_rdp_to_server_IPv6(self):
916 daac4017 John Giannelos
        "Test RDP connection to server public IPv6 works"""
917 daac4017 John Giannelos
        self._skipIf(not self.is_windows, "only valid for Windows servers")
918 daac4017 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
919 946da8b6 John Giannelos
920 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
921 daac4017 John Giannelos
        ipv6 = self._get_ipv6(server)
922 6e168615 Ilias Tsitsimpis
        sock = self._get_tcp_connection(socket.AF_INET6, ipv6, 3389)
923 5a140b23 Vangelis Koukis
924 daac4017 John Giannelos
        # No actual RDP processing done. We assume the RDP server is there
925 daac4017 John Giannelos
        # if the connection to the RDP port is successful.
926 daac4017 John Giannelos
        sock.close()
927 5a140b23 Vangelis Koukis
928 daac4017 John Giannelos
    def test_016_personality_is_enforced(self):
929 daac4017 John Giannelos
        """Test file injection for personality enforcement"""
930 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only implemented for Linux servers")
931 6e168615 Ilias Tsitsimpis
        self._skipIf(self.personality is None, "No personality file selected")
932 f89d0238 John Giannelos
933 daac4017 John Giannelos
        log.info("Trying to inject file for personality enforcement")
934 f89d0238 John Giannelos
935 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid)
936 77054bf5 John Giannelos
937 daac4017 John Giannelos
        for inj_file in self.personality:
938 daac4017 John Giannelos
            equal_files = self._check_file_through_ssh(self._get_ipv4(server),
939 daac4017 John Giannelos
                                                       inj_file['owner'],
940 daac4017 John Giannelos
                                                       self.passwd,
941 daac4017 John Giannelos
                                                       inj_file['path'],
942 daac4017 John Giannelos
                                                       inj_file['contents'])
943 daac4017 John Giannelos
            self.assertTrue(equal_files)
944 8252d64f John Giannelos
945 4fdd25ab Vangelis Koukis
    def test_017_submit_delete_request(self):
946 4fdd25ab Vangelis Koukis
        """Test submit request to delete server"""
947 f89d0238 John Giannelos
948 f89d0238 John Giannelos
        log.info("Deleting server")
949 f89d0238 John Giannelos
950 4fdd25ab Vangelis Koukis
        self.client.delete_server(self.serverid)
951 4fdd25ab Vangelis Koukis
952 4fdd25ab Vangelis Koukis
    def test_018_server_becomes_deleted(self):
953 4fdd25ab Vangelis Koukis
        """Test server becomes DELETED"""
954 f89d0238 John Giannelos
955 f89d0238 John Giannelos
        log.info("Testing if server becomes DELETED")
956 f89d0238 John Giannelos
957 6e168615 Ilias Tsitsimpis
        self._insist_on_status_transition(
958 6e168615 Ilias Tsitsimpis
            "ACTIVE", "DELETED", self.action_timeout, self.action_timeout)
959 4fdd25ab Vangelis Koukis
960 4fdd25ab Vangelis Koukis
    def test_019_server_no_longer_in_server_list(self):
961 4fdd25ab Vangelis Koukis
        """Test server is no longer in server list"""
962 f89d0238 John Giannelos
963 f89d0238 John Giannelos
        log.info("Test if server is no longer listed")
964 f89d0238 John Giannelos
965 4fdd25ab Vangelis Koukis
        servers = self.client.list_servers()
966 21bbbc9b Vangelis Koukis
        self.assertNotIn(self.serverid, [s["id"] for s in servers])
967 21bbbc9b Vangelis Koukis
968 21bbbc9b Vangelis Koukis
969 9e4682b5 John Giannelos
class NetworkTestCase(unittest.TestCase):
970 e94a9d8c John Giannelos
    """ Testing networking in cyclades """
971 8252d64f John Giannelos
972 9e4682b5 John Giannelos
    @classmethod
973 e94a9d8c John Giannelos
    def setUpClass(cls):
974 e94a9d8c John Giannelos
        "Initialize kamaki, get list of current networks"
975 567ffb85 John Giannelos
976 567ffb85 John Giannelos
        cls.client = CycladesClient(API, TOKEN)
977 567ffb85 John Giannelos
        cls.compute = ComputeClient(API, TOKEN)
978 9e4682b5 John Giannelos
979 8252d64f John Giannelos
        cls.servername = "%s%s for %s" % (SNF_TEST_PREFIX,
980 8252d64f John Giannelos
                                          TEST_RUN_ID,
981 8252d64f John Giannelos
                                          cls.imagename)
982 91de9b55 John Giannelos
983 91de9b55 John Giannelos
        #Dictionary initialization for the vms credentials
984 91de9b55 John Giannelos
        cls.serverid = dict()
985 91de9b55 John Giannelos
        cls.username = dict()
986 91de9b55 John Giannelos
        cls.password = dict()
987 846980fe John Giannelos
        cls.is_windows = cls.imagename.lower().find("windows") >= 0
988 e49bdb7c John Giannelos
989 66eba2cf John Giannelos
        cls.result_dict = dict()
990 66eba2cf John Giannelos
991 e49bdb7c John Giannelos
    def _skipIf(self, condition, msg):
992 e49bdb7c John Giannelos
        if condition:
993 e49bdb7c John Giannelos
            self.skipTest(msg)
994 91de9b55 John Giannelos
995 1b40b5e3 John Giannelos
    def _get_ipv4(self, server):
996 1b40b5e3 John Giannelos
        """Get the public IPv4 of a server from the detailed server info"""
997 1b40b5e3 John Giannelos
998 bcb7c357 Ilias Tsitsimpis
        nics = server["attachments"]
999 2aaa1336 John Giannelos
1000 e50133da John Giannelos
        for nic in nics:
1001 e50133da John Giannelos
            net_id = nic["network_id"]
1002 6e168615 Ilias Tsitsimpis
            if self.client.get_network_details(net_id)["public"]:
1003 e50133da John Giannelos
                public_addrs = nic["ipv4"]
1004 2aaa1336 John Giannelos
1005 6e168615 Ilias Tsitsimpis
        self.assertTrue(public_addrs is not None)
1006 2aaa1336 John Giannelos
1007 6e168615 Ilias Tsitsimpis
        return public_addrs
1008 8252d64f John Giannelos
1009 6e168615 Ilias Tsitsimpis
    def _connect_loginname(self, os_value):
1010 1b40b5e3 John Giannelos
        """Return the login name for connections based on the server OS"""
1011 6e168615 Ilias Tsitsimpis
        if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
1012 1b40b5e3 John Giannelos
            return "user"
1013 6e168615 Ilias Tsitsimpis
        elif os_value in ("windows", "windows_alpha1"):
1014 1b40b5e3 John Giannelos
            return "Administrator"
1015 1b40b5e3 John Giannelos
        else:
1016 1b40b5e3 John Giannelos
            return "root"
1017 1b40b5e3 John Giannelos
1018 88736f65 John Giannelos
    def _ping_once(self, ip):
1019 8252d64f John Giannelos
1020 88736f65 John Giannelos
        """Test server responds to a single IPv4 or IPv6 ping"""
1021 88736f65 John Giannelos
        cmd = "ping -c 2 -w 3 %s" % (ip)
1022 88736f65 John Giannelos
        ping = subprocess.Popen(cmd, shell=True,
1023 88736f65 John Giannelos
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1024 88736f65 John Giannelos
        (stdout, stderr) = ping.communicate()
1025 88736f65 John Giannelos
        ret = ping.wait()
1026 8252d64f John Giannelos
1027 88736f65 John Giannelos
        return (ret == 0)
1028 88736f65 John Giannelos
1029 740a5649 John Giannelos
    def test_00001a_submit_create_server_A(self):
1030 91de9b55 John Giannelos
        """Test submit create server request"""
1031 f89d0238 John Giannelos
1032 f89d0238 John Giannelos
        log.info("Creating test server A")
1033 f89d0238 John Giannelos
1034 91de9b55 John Giannelos
        serverA = self.client.create_server(self.servername, self.flavorid,
1035 ae139e8a John Giannelos
                                            self.imageid, personality=None)
1036 91de9b55 John Giannelos
1037 c54e3d4c John Giannelos
        self.assertEqual(serverA["name"], self.servername)
1038 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(serverA["flavor"], self.flavorid)
1039 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(serverA["image"], self.imageid)
1040 c54e3d4c John Giannelos
        self.assertEqual(serverA["status"], "BUILD")
1041 91de9b55 John Giannelos
1042 91de9b55 John Giannelos
        # Update class attributes to reflect data on building server
1043 08748d73 John Giannelos
        self.serverid['A'] = serverA["id"]
1044 08748d73 John Giannelos
        self.username['A'] = None
1045 08748d73 John Giannelos
        self.password['A'] = serverA["adminPass"]
1046 91de9b55 John Giannelos
1047 81e8cbf6 John Giannelos
        log.info("Server A id:" + str(serverA["id"]))
1048 81e8cbf6 John Giannelos
        log.info("Server password " + (self.password['A']))
1049 8252d64f John Giannelos
1050 66eba2cf John Giannelos
        self.result_dict["Server A ID"] = str(serverA["id"])
1051 66eba2cf John Giannelos
        self.result_dict["Server A password"] = serverA["adminPass"]
1052 6e168615 Ilias Tsitsimpis
1053 740a5649 John Giannelos
    def test_00001b_serverA_becomes_active(self):
1054 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
1055 8252d64f John Giannelos
1056 f89d0238 John Giannelos
        log.info("Waiting until test server A becomes ACTIVE")
1057 66eba2cf John Giannelos
        self.result_dict.clear()
1058 91de9b55 John Giannelos
1059 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1060 91de9b55 John Giannelos
        while True:
1061 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
1062 91de9b55 John Giannelos
            status = d['status']
1063 91de9b55 John Giannelos
            if status == 'ACTIVE':
1064 91de9b55 John Giannelos
                active = True
1065 91de9b55 John Giannelos
                break
1066 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
1067 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1068 91de9b55 John Giannelos
            else:
1069 91de9b55 John Giannelos
                time.sleep(self.query_interval)
1070 91de9b55 John Giannelos
1071 91de9b55 John Giannelos
        self.assertTrue(active)
1072 91de9b55 John Giannelos
1073 740a5649 John Giannelos
    def test_00002a_submit_create_server_B(self):
1074 fade8dab John Giannelos
        """Test submit create server request"""
1075 8252d64f John Giannelos
1076 f89d0238 John Giannelos
        log.info("Creating test server B")
1077 6e168615 Ilias Tsitsimpis
1078 fade8dab John Giannelos
        serverB = self.client.create_server(self.servername, self.flavorid,
1079 ae139e8a John Giannelos
                                            self.imageid, personality=None)
1080 ae139e8a John Giannelos
1081 fade8dab John Giannelos
        self.assertEqual(serverB["name"], self.servername)
1082 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(serverB["flavor"], self.flavorid)
1083 bcb7c357 Ilias Tsitsimpis
        self.assertEqual(serverB["image"], self.imageid)
1084 fade8dab John Giannelos
        self.assertEqual(serverB["status"], "BUILD")
1085 fade8dab John Giannelos
1086 fade8dab John Giannelos
        # Update class attributes to reflect data on building server
1087 fade8dab John Giannelos
        self.serverid['B'] = serverB["id"]
1088 fade8dab John Giannelos
        self.username['B'] = None
1089 fade8dab John Giannelos
        self.password['B'] = serverB["adminPass"]
1090 fade8dab John Giannelos
1091 81e8cbf6 John Giannelos
        log.info("Server B id: " + str(serverB["id"]))
1092 81e8cbf6 John Giannelos
        log.info("Password " + (self.password['B']))
1093 ae139e8a John Giannelos
1094 66eba2cf John Giannelos
        self.result_dict.clear()
1095 66eba2cf John Giannelos
        self.result_dict["Server B ID"] = str(serverB["id"])
1096 66eba2cf John Giannelos
        self.result_dict["Server B password"] = serverB["adminPass"]
1097 66eba2cf John Giannelos
1098 740a5649 John Giannelos
    def test_00002b_serverB_becomes_active(self):
1099 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
1100 91de9b55 John Giannelos
1101 f89d0238 John Giannelos
        log.info("Waiting until test server B becomes ACTIVE")
1102 66eba2cf John Giannelos
        self.result_dict.clear()
1103 f89d0238 John Giannelos
1104 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1105 91de9b55 John Giannelos
        while True:
1106 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
1107 91de9b55 John Giannelos
            status = d['status']
1108 91de9b55 John Giannelos
            if status == 'ACTIVE':
1109 91de9b55 John Giannelos
                active = True
1110 91de9b55 John Giannelos
                break
1111 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
1112 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1113 91de9b55 John Giannelos
            else:
1114 91de9b55 John Giannelos
                time.sleep(self.query_interval)
1115 91de9b55 John Giannelos
1116 91de9b55 John Giannelos
        self.assertTrue(active)
1117 567ffb85 John Giannelos
1118 9e4682b5 John Giannelos
    def test_001_create_network(self):
1119 e94a9d8c John Giannelos
        """Test submit create network request"""
1120 f89d0238 John Giannelos
1121 f89d0238 John Giannelos
        log.info("Submit new network request")
1122 66eba2cf John Giannelos
        self.result_dict.clear()
1123 6e168615 Ilias Tsitsimpis
1124 2bcfb712 John Giannelos
        name = SNF_TEST_PREFIX + TEST_RUN_ID
1125 6e168615 Ilias Tsitsimpis
        #previous_num = len(self.client.list_networks())
1126 9b1e6145 Christos Stavrakakis
        network = self.client.create_network(name, cidr='10.0.1.0/28',
1127 9b1e6145 Christos Stavrakakis
                                             dhcp=True)
1128 8252d64f John Giannelos
1129 9e4682b5 John Giannelos
        #Test if right name is assigned
1130 e94a9d8c John Giannelos
        self.assertEqual(network['name'], name)
1131 8252d64f John Giannelos
1132 9e4682b5 John Giannelos
        # Update class attributes
1133 e94a9d8c John Giannelos
        cls = type(self)
1134 e94a9d8c John Giannelos
        cls.networkid = network['id']
1135 6e168615 Ilias Tsitsimpis
        #networks = self.client.list_networks()
1136 9e4682b5 John Giannelos
1137 2aaa1336 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1138 2aaa1336 John Giannelos
1139 9e4682b5 John Giannelos
        #Test if new network is created
1140 2aaa1336 John Giannelos
        while True:
1141 2aaa1336 John Giannelos
            d = self.client.get_network_details(network['id'])
1142 2aaa1336 John Giannelos
            if d['status'] == 'ACTIVE':
1143 2aaa1336 John Giannelos
                connected = True
1144 2aaa1336 John Giannelos
                break
1145 2aaa1336 John Giannelos
            elif time.time() > fail_tmout:
1146 2aaa1336 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1147 2aaa1336 John Giannelos
            else:
1148 2aaa1336 John Giannelos
                log.info("Waiting for network to become ACTIVE")
1149 2aaa1336 John Giannelos
                time.sleep(self.query_interval)
1150 2aaa1336 John Giannelos
1151 2aaa1336 John Giannelos
        self.assertTrue(connected)
1152 8252d64f John Giannelos
1153 66eba2cf John Giannelos
        self.result_dict["Private network ID"] = str(network['id'])
1154 66eba2cf John Giannelos
1155 9e4682b5 John Giannelos
    def test_002_connect_to_network(self):
1156 4573ea07 John Giannelos
        """Test connect VMs to network"""
1157 9e4682b5 John Giannelos
1158 f89d0238 John Giannelos
        log.info("Connect VMs to private network")
1159 66eba2cf John Giannelos
        self.result_dict.clear()
1160 f89d0238 John Giannelos
1161 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['A'], self.networkid)
1162 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['B'], self.networkid)
1163 8252d64f John Giannelos
1164 65462ca9 John Giannelos
        #Insist on connecting until action timeout
1165 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1166 9e4682b5 John Giannelos
1167 65462ca9 John Giannelos
        while True:
1168 2aaa1336 John Giannelos
1169 6e168615 Ilias Tsitsimpis
            netsA = [x['network_id']
1170 6e168615 Ilias Tsitsimpis
                     for x in self.client.get_server_details(
1171 bcb7c357 Ilias Tsitsimpis
                         self.serverid['A'])['attachments']]
1172 6e168615 Ilias Tsitsimpis
            netsB = [x['network_id']
1173 6e168615 Ilias Tsitsimpis
                     for x in self.client.get_server_details(
1174 bcb7c357 Ilias Tsitsimpis
                         self.serverid['B'])['attachments']]
1175 2aaa1336 John Giannelos
1176 2aaa1336 John Giannelos
            if (self.networkid in netsA) and (self.networkid in netsB):
1177 65462ca9 John Giannelos
                conn_exists = True
1178 de2461ec John Giannelos
                break
1179 de2461ec John Giannelos
            elif time.time() > fail_tmout:
1180 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1181 65462ca9 John Giannelos
            else:
1182 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1183 6e168615 Ilias Tsitsimpis
1184 daac4017 John Giannelos
        #Adding private IPs to class attributes
1185 daac4017 John Giannelos
        cls = type(self)
1186 daac4017 John Giannelos
        cls.priv_ip = dict()
1187 daac4017 John Giannelos
1188 6e168615 Ilias Tsitsimpis
        nicsA = self.client.get_server_details(
1189 bcb7c357 Ilias Tsitsimpis
            self.serverid['A'])['attachments']
1190 6e168615 Ilias Tsitsimpis
        nicsB = self.client.get_server_details(
1191 bcb7c357 Ilias Tsitsimpis
            self.serverid['B'])['attachments']
1192 daac4017 John Giannelos
1193 daac4017 John Giannelos
        if conn_exists:
1194 daac4017 John Giannelos
            for nic in nicsA:
1195 daac4017 John Giannelos
                if nic["network_id"] == self.networkid:
1196 daac4017 John Giannelos
                    cls.priv_ip["A"] = nic["ipv4"]
1197 8bf886d0 Ilias Tsitsimpis
            self.result_dict["Server A private IP"] = str(cls.priv_ip["A"])
1198 daac4017 John Giannelos
1199 daac4017 John Giannelos
            for nic in nicsB:
1200 daac4017 John Giannelos
                if nic["network_id"] == self.networkid:
1201 daac4017 John Giannelos
                    cls.priv_ip["B"] = nic["ipv4"]
1202 8bf886d0 Ilias Tsitsimpis
            self.result_dict["Server B private IP"] = str(cls.priv_ip["B"])
1203 65462ca9 John Giannelos
1204 65462ca9 John Giannelos
        self.assertTrue(conn_exists)
1205 9b1e6145 Christos Stavrakakis
        self.assertIsNot(cls.priv_ip["A"], None)
1206 9b1e6145 Christos Stavrakakis
        self.assertIsNot(cls.priv_ip["B"], None)
1207 9e4682b5 John Giannelos
1208 88736f65 John Giannelos
    def test_002a_reboot(self):
1209 f89d0238 John Giannelos
        """Rebooting server A"""
1210 f89d0238 John Giannelos
1211 f89d0238 John Giannelos
        log.info("Rebooting server A")
1212 f89d0238 John Giannelos
1213 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['A'])
1214 8252d64f John Giannelos
1215 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1216 4573ea07 John Giannelos
        while True:
1217 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
1218 4573ea07 John Giannelos
            status = d['status']
1219 81e8cbf6 John Giannelos
            if status == 'STOPPED':
1220 81e8cbf6 John Giannelos
                break
1221 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
1222 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1223 81e8cbf6 John Giannelos
            else:
1224 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
1225 81e8cbf6 John Giannelos
1226 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['A'])
1227 81e8cbf6 John Giannelos
1228 81e8cbf6 John Giannelos
        while True:
1229 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
1230 81e8cbf6 John Giannelos
            status = d['status']
1231 4573ea07 John Giannelos
            if status == 'ACTIVE':
1232 4573ea07 John Giannelos
                active = True
1233 4573ea07 John Giannelos
                break
1234 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
1235 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1236 4573ea07 John Giannelos
            else:
1237 4573ea07 John Giannelos
                time.sleep(self.query_interval)
1238 8252d64f John Giannelos
1239 4573ea07 John Giannelos
        self.assertTrue(active)
1240 88736f65 John Giannelos
1241 daac4017 John Giannelos
    def test_002b_ping_server_A(self):
1242 daac4017 John Giannelos
        "Test if server A responds to IPv4 pings"
1243 4573ea07 John Giannelos
1244 daac4017 John Giannelos
        log.info("Testing if server A responds to IPv4 pings ")
1245 66eba2cf John Giannelos
        self.result_dict.clear()
1246 f89d0238 John Giannelos
1247 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1248 daac4017 John Giannelos
        ip = self._get_ipv4(server)
1249 8252d64f John Giannelos
1250 daac4017 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1251 8252d64f John Giannelos
1252 daac4017 John Giannelos
        s = False
1253 6e168615 Ilias Tsitsimpis
1254 66eba2cf John Giannelos
        self.result_dict["Server A public IP"] = str(ip)
1255 88736f65 John Giannelos
1256 daac4017 John Giannelos
        while True:
1257 88736f65 John Giannelos
1258 daac4017 John Giannelos
            if self._ping_once(ip):
1259 daac4017 John Giannelos
                s = True
1260 daac4017 John Giannelos
                break
1261 88736f65 John Giannelos
1262 daac4017 John Giannelos
            elif time.time() > fail_tmout:
1263 daac4017 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1264 88736f65 John Giannelos
1265 daac4017 John Giannelos
            else:
1266 daac4017 John Giannelos
                time.sleep(self.query_interval)
1267 88736f65 John Giannelos
1268 daac4017 John Giannelos
        self.assertTrue(s)
1269 4573ea07 John Giannelos
1270 4573ea07 John Giannelos
    def test_002c_reboot(self):
1271 f89d0238 John Giannelos
        """Reboot server B"""
1272 f89d0238 John Giannelos
1273 f89d0238 John Giannelos
        log.info("Rebooting server B")
1274 66eba2cf John Giannelos
        self.result_dict.clear()
1275 f89d0238 John Giannelos
1276 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['B'])
1277 8252d64f John Giannelos
1278 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1279 4573ea07 John Giannelos
        while True:
1280 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
1281 4573ea07 John Giannelos
            status = d['status']
1282 81e8cbf6 John Giannelos
            if status == 'STOPPED':
1283 81e8cbf6 John Giannelos
                break
1284 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
1285 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1286 81e8cbf6 John Giannelos
            else:
1287 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
1288 81e8cbf6 John Giannelos
1289 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['B'])
1290 81e8cbf6 John Giannelos
1291 81e8cbf6 John Giannelos
        while True:
1292 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
1293 81e8cbf6 John Giannelos
            status = d['status']
1294 4573ea07 John Giannelos
            if status == 'ACTIVE':
1295 4573ea07 John Giannelos
                active = True
1296 4573ea07 John Giannelos
                break
1297 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
1298 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1299 4573ea07 John Giannelos
            else:
1300 4573ea07 John Giannelos
                time.sleep(self.query_interval)
1301 8252d64f John Giannelos
1302 4573ea07 John Giannelos
        self.assertTrue(active)
1303 8252d64f John Giannelos
1304 daac4017 John Giannelos
    def test_002d_ping_server_B(self):
1305 daac4017 John Giannelos
        """Test if server B responds to IPv4 pings"""
1306 4573ea07 John Giannelos
1307 daac4017 John Giannelos
        log.info("Testing if server B responds to IPv4 pings")
1308 66eba2cf John Giannelos
        self.result_dict.clear()
1309 6e168615 Ilias Tsitsimpis
1310 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1311 daac4017 John Giannelos
        ip = self._get_ipv4(server)
1312 8252d64f John Giannelos
1313 daac4017 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1314 8252d64f John Giannelos
1315 daac4017 John Giannelos
        s = False
1316 88736f65 John Giannelos
1317 66eba2cf John Giannelos
        self.result_dict["Server B public IP"] = str(ip)
1318 66eba2cf John Giannelos
1319 daac4017 John Giannelos
        while True:
1320 daac4017 John Giannelos
            if self._ping_once(ip):
1321 daac4017 John Giannelos
                s = True
1322 daac4017 John Giannelos
                break
1323 88736f65 John Giannelos
1324 daac4017 John Giannelos
            elif time.time() > fail_tmout:
1325 daac4017 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1326 88736f65 John Giannelos
1327 daac4017 John Giannelos
            else:
1328 daac4017 John Giannelos
                time.sleep(self.query_interval)
1329 88736f65 John Giannelos
1330 daac4017 John Giannelos
        self.assertTrue(s)
1331 88736f65 John Giannelos
1332 daac4017 John Giannelos
    def test_003a_setup_interface_A(self):
1333 8bf886d0 Ilias Tsitsimpis
        """Setup eth1 for server A"""
1334 f89d0238 John Giannelos
1335 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1336 e49bdb7c John Giannelos
1337 daac4017 John Giannelos
        log.info("Setting up interface eth1 for server A")
1338 66eba2cf John Giannelos
        self.result_dict.clear()
1339 ae139e8a John Giannelos
1340 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1341 daac4017 John Giannelos
        image = self.client.get_image_details(self.imageid)
1342 bcb7c357 Ilias Tsitsimpis
        os_value = image['metadata']['os']
1343 8252d64f John Giannelos
1344 bcb7c357 Ilias Tsitsimpis
        users = image["metadata"].get("users", None)
1345 daac4017 John Giannelos
        userlist = users.split()
1346 d5cc50b3 John Giannelos
1347 daac4017 John Giannelos
        if "root" in userlist:
1348 daac4017 John Giannelos
            loginname = "root"
1349 6e168615 Ilias Tsitsimpis
        elif users is None:
1350 6e168615 Ilias Tsitsimpis
            loginname = self._connect_loginname(os_value)
1351 daac4017 John Giannelos
        else:
1352 daac4017 John Giannelos
            loginname = choice(userlist)
1353 1b40b5e3 John Giannelos
1354 daac4017 John Giannelos
        hostip = self._get_ipv4(server)
1355 daac4017 John Giannelos
        myPass = self.password['A']
1356 8252d64f John Giannelos
1357 daac4017 John Giannelos
        log.info("SSH in server A as %s/%s" % (loginname, myPass))
1358 8bf886d0 Ilias Tsitsimpis
        command = "ifconfig eth1 %s && ifconfig eth1 | " \
1359 8bf886d0 Ilias Tsitsimpis
                  "grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'" \
1360 8bf886d0 Ilias Tsitsimpis
                  % self.priv_ip["A"]
1361 2a410f76 Ilias Tsitsimpis
        output, status = _ssh_execute(
1362 2a410f76 Ilias Tsitsimpis
            hostip, loginname, myPass, command)
1363 8252d64f John Giannelos
1364 2a410f76 Ilias Tsitsimpis
        self.assertEquals(status, 0)
1365 8bf886d0 Ilias Tsitsimpis
        self.assertEquals(output[0].strip(), self.priv_ip["A"])
1366 1b40b5e3 John Giannelos
1367 daac4017 John Giannelos
    def test_003b_setup_interface_B(self):
1368 daac4017 John Giannelos
        """Setup eth1 for server B"""
1369 1b40b5e3 John Giannelos
1370 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1371 e49bdb7c John Giannelos
1372 daac4017 John Giannelos
        log.info("Setting up interface eth1 for server B")
1373 ae139e8a John Giannelos
1374 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1375 daac4017 John Giannelos
        image = self.client.get_image_details(self.imageid)
1376 bcb7c357 Ilias Tsitsimpis
        os_value = image['metadata']['os']
1377 8252d64f John Giannelos
1378 bcb7c357 Ilias Tsitsimpis
        users = image["metadata"].get("users", None)
1379 daac4017 John Giannelos
        userlist = users.split()
1380 d5cc50b3 John Giannelos
1381 daac4017 John Giannelos
        if "root" in userlist:
1382 daac4017 John Giannelos
            loginname = "root"
1383 6e168615 Ilias Tsitsimpis
        elif users is None:
1384 6e168615 Ilias Tsitsimpis
            loginname = self._connect_loginname(os_value)
1385 daac4017 John Giannelos
        else:
1386 daac4017 John Giannelos
            loginname = choice(userlist)
1387 d5cc50b3 John Giannelos
1388 daac4017 John Giannelos
        hostip = self._get_ipv4(server)
1389 daac4017 John Giannelos
        myPass = self.password['B']
1390 740a5649 John Giannelos
1391 daac4017 John Giannelos
        log.info("SSH in server B as %s/%s" % (loginname, myPass))
1392 8bf886d0 Ilias Tsitsimpis
        command = "ifconfig eth1 %s && ifconfig eth1 | " \
1393 8bf886d0 Ilias Tsitsimpis
                  "grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'" \
1394 8bf886d0 Ilias Tsitsimpis
                  % self.priv_ip["B"]
1395 2a410f76 Ilias Tsitsimpis
        output, status = _ssh_execute(
1396 2a410f76 Ilias Tsitsimpis
            hostip, loginname, myPass, command)
1397 1b40b5e3 John Giannelos
1398 2a410f76 Ilias Tsitsimpis
        self.assertEquals(status, 0)
1399 8bf886d0 Ilias Tsitsimpis
        self.assertEquals(output[0].strip(), self.priv_ip["B"])
1400 ae139e8a John Giannelos
1401 daac4017 John Giannelos
    def test_003c_test_connection_exists(self):
1402 daac4017 John Giannelos
        """Ping server B from server A to test if connection exists"""
1403 1b40b5e3 John Giannelos
1404 daac4017 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1405 e49bdb7c John Giannelos
1406 daac4017 John Giannelos
        log.info("Testing if server A is actually connected to server B")
1407 f89d0238 John Giannelos
1408 daac4017 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1409 daac4017 John Giannelos
        image = self.client.get_image_details(self.imageid)
1410 bcb7c357 Ilias Tsitsimpis
        os_value = image['metadata']['os']
1411 daac4017 John Giannelos
        hostip = self._get_ipv4(server)
1412 d5cc50b3 John Giannelos
1413 bcb7c357 Ilias Tsitsimpis
        users = image["metadata"].get("users", None)
1414 daac4017 John Giannelos
        userlist = users.split()
1415 d5cc50b3 John Giannelos
1416 daac4017 John Giannelos
        if "root" in userlist:
1417 daac4017 John Giannelos
            loginname = "root"
1418 6e168615 Ilias Tsitsimpis
        elif users is None:
1419 6e168615 Ilias Tsitsimpis
            loginname = self._connect_loginname(os_value)
1420 daac4017 John Giannelos
        else:
1421 daac4017 John Giannelos
            loginname = choice(userlist)
1422 1b40b5e3 John Giannelos
1423 daac4017 John Giannelos
        myPass = self.password['A']
1424 88736f65 John Giannelos
1425 daac4017 John Giannelos
        cmd = "if ping -c 2 -w 3 %s >/dev/null; \
1426 daac4017 John Giannelos
               then echo \'True\'; fi;" % self.priv_ip["B"]
1427 2a410f76 Ilias Tsitsimpis
        lines, status = _ssh_execute(
1428 2a410f76 Ilias Tsitsimpis
            hostip, loginname, myPass, cmd)
1429 1b40b5e3 John Giannelos
1430 daac4017 John Giannelos
        exists = False
1431 4573ea07 John Giannelos
1432 daac4017 John Giannelos
        if 'True\n' in lines:
1433 daac4017 John Giannelos
            exists = True
1434 1b40b5e3 John Giannelos
1435 daac4017 John Giannelos
        self.assertTrue(exists)
1436 1b40b5e3 John Giannelos
1437 88736f65 John Giannelos
    def test_004_disconnect_from_network(self):
1438 4573ea07 John Giannelos
        "Disconnecting server A and B from network"
1439 4573ea07 John Giannelos
1440 f89d0238 John Giannelos
        log.info("Disconnecting servers from private network")
1441 f89d0238 John Giannelos
1442 f97dce4d John Giannelos
        prev_state = self.client.get_network_details(self.networkid)
1443 bcb7c357 Ilias Tsitsimpis
        prev_nics = prev_state['attachments']
1444 6e168615 Ilias Tsitsimpis
        #prev_conn = len(prev_nics)
1445 2aaa1336 John Giannelos
1446 6e168615 Ilias Tsitsimpis
        nicsA = [x['id']
1447 6e168615 Ilias Tsitsimpis
                 for x in self.client.get_server_details(
1448 bcb7c357 Ilias Tsitsimpis
                     self.serverid['A'])['attachments']]
1449 6e168615 Ilias Tsitsimpis
        nicsB = [x['id']
1450 6e168615 Ilias Tsitsimpis
                 for x in self.client.get_server_details(
1451 bcb7c357 Ilias Tsitsimpis
                     self.serverid['B'])['attachments']]
1452 2aaa1336 John Giannelos
1453 2aaa1336 John Giannelos
        for nic in prev_nics:
1454 2aaa1336 John Giannelos
            if nic in nicsA:
1455 2aaa1336 John Giannelos
                self.client.disconnect_server(self.serverid['A'], nic)
1456 2aaa1336 John Giannelos
            if nic in nicsB:
1457 2aaa1336 John Giannelos
                self.client.disconnect_server(self.serverid['B'], nic)
1458 e94a9d8c John Giannelos
1459 65462ca9 John Giannelos
        #Insist on deleting until action timeout
1460 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1461 9e4682b5 John Giannelos
1462 65462ca9 John Giannelos
        while True:
1463 6e168615 Ilias Tsitsimpis
            netsA = [x['network_id']
1464 6e168615 Ilias Tsitsimpis
                     for x in self.client.get_server_details(
1465 bcb7c357 Ilias Tsitsimpis
                         self.serverid['A'])['attachments']]
1466 6e168615 Ilias Tsitsimpis
            netsB = [x['network_id']
1467 6e168615 Ilias Tsitsimpis
                     for x in self.client.get_server_details(
1468 bcb7c357 Ilias Tsitsimpis
                         self.serverid['B'])['attachments']]
1469 6e168615 Ilias Tsitsimpis
1470 6e168615 Ilias Tsitsimpis
            #connected = (self.client.get_network_details(self.networkid))
1471 bcb7c357 Ilias Tsitsimpis
            #connections = connected['attachments']
1472 2aaa1336 John Giannelos
            if (self.networkid not in netsA) and (self.networkid not in netsB):
1473 65462ca9 John Giannelos
                conn_exists = False
1474 de2461ec John Giannelos
                break
1475 de2461ec John Giannelos
            elif time.time() > fail_tmout:
1476 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1477 65462ca9 John Giannelos
            else:
1478 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1479 65462ca9 John Giannelos
1480 65462ca9 John Giannelos
        self.assertFalse(conn_exists)
1481 9e4682b5 John Giannelos
1482 88736f65 John Giannelos
    def test_005_destroy_network(self):
1483 e94a9d8c John Giannelos
        """Test submit delete network request"""
1484 f89d0238 John Giannelos
1485 f89d0238 John Giannelos
        log.info("Submitting delete network request")
1486 f89d0238 John Giannelos
1487 8252d64f John Giannelos
        self.client.delete_network(self.networkid)
1488 e50133da John Giannelos
1489 2aaa1336 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1490 2aaa1336 John Giannelos
1491 2aaa1336 John Giannelos
        while True:
1492 e94a9d8c John Giannelos
1493 2aaa1336 John Giannelos
            curr_net = []
1494 2aaa1336 John Giannelos
            networks = self.client.list_networks()
1495 2aaa1336 John Giannelos
1496 2aaa1336 John Giannelos
            for net in networks:
1497 2aaa1336 John Giannelos
                curr_net.append(net['id'])
1498 2aaa1336 John Giannelos
1499 2aaa1336 John Giannelos
            if self.networkid not in curr_net:
1500 2aaa1336 John Giannelos
                self.assertTrue(self.networkid not in curr_net)
1501 2aaa1336 John Giannelos
                break
1502 65462ca9 John Giannelos
1503 2aaa1336 John Giannelos
            elif time.time() > fail_tmout:
1504 2aaa1336 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1505 2aaa1336 John Giannelos
1506 2aaa1336 John Giannelos
            else:
1507 2aaa1336 John Giannelos
                time.sleep(self.query_interval)
1508 2aaa1336 John Giannelos
1509 88736f65 John Giannelos
    def test_006_cleanup_servers(self):
1510 65462ca9 John Giannelos
        """Cleanup servers created for this test"""
1511 f89d0238 John Giannelos
1512 f89d0238 John Giannelos
        log.info("Delete servers created for this test")
1513 f89d0238 John Giannelos
1514 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['A'])
1515 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['B'])
1516 91de9b55 John Giannelos
1517 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1518 65462ca9 John Giannelos
1519 65462ca9 John Giannelos
        #Ensure server gets deleted
1520 8252d64f John Giannelos
        status = dict()
1521 91de9b55 John Giannelos
1522 65462ca9 John Giannelos
        while True:
1523 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['A'])
1524 91de9b55 John Giannelos
            status['A'] = details['status']
1525 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['B'])
1526 91de9b55 John Giannelos
            status['B'] = details['status']
1527 91de9b55 John Giannelos
            if (status['A'] == 'DELETED') and (status['B'] == 'DELETED'):
1528 65462ca9 John Giannelos
                deleted = True
1529 de2461ec John Giannelos
                break
1530 8252d64f John Giannelos
            elif time.time() > fail_tmout:
1531 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1532 65462ca9 John Giannelos
            else:
1533 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1534 8252d64f John Giannelos
1535 65462ca9 John Giannelos
        self.assertTrue(deleted)
1536 e94a9d8c John Giannelos
1537 4573ea07 John Giannelos
1538 21bbbc9b Vangelis Koukis
class TestRunnerProcess(Process):
1539 21bbbc9b Vangelis Koukis
    """A distinct process used to execute part of the tests in parallel"""
1540 21bbbc9b Vangelis Koukis
    def __init__(self, **kw):
1541 21bbbc9b Vangelis Koukis
        Process.__init__(self, **kw)
1542 96da37c8 John Giannelos
        kwargs = kw["kwargs"]
1543 21bbbc9b Vangelis Koukis
        self.testq = kwargs["testq"]
1544 2aaa1336 John Giannelos
        self.worker_folder = kwargs["worker_folder"]
1545 21bbbc9b Vangelis Koukis
1546 21bbbc9b Vangelis Koukis
    def run(self):
1547 21bbbc9b Vangelis Koukis
        # Make sure this test runner process dies with the parent
1548 21bbbc9b Vangelis Koukis
        # and is not left behind.
1549 21bbbc9b Vangelis Koukis
        #
1550 21bbbc9b Vangelis Koukis
        # WARNING: This uses the prctl(2) call and is
1551 21bbbc9b Vangelis Koukis
        # Linux-specific.
1552 2aaa1336 John Giannelos
1553 21bbbc9b Vangelis Koukis
        prctl.set_pdeathsig(signal.SIGHUP)
1554 21bbbc9b Vangelis Koukis
1555 2aaa1336 John Giannelos
        multi = logging.getLogger("multiprocess")
1556 2aaa1336 John Giannelos
1557 21bbbc9b Vangelis Koukis
        while True:
1558 2aaa1336 John Giannelos
            multi.debug("I am process %d, GETting from queue is %s" %
1559 6e168615 Ilias Tsitsimpis
                        (os.getpid(), self.testq))
1560 21bbbc9b Vangelis Koukis
            msg = self.testq.get()
1561 2aaa1336 John Giannelos
1562 2aaa1336 John Giannelos
            multi.debug("Dequeued msg: %s" % msg)
1563 21bbbc9b Vangelis Koukis
1564 21bbbc9b Vangelis Koukis
            if msg == "TEST_RUNNER_TERMINATE":
1565 21bbbc9b Vangelis Koukis
                raise SystemExit
1566 2aaa1336 John Giannelos
1567 21bbbc9b Vangelis Koukis
            elif issubclass(msg, unittest.TestCase):
1568 21bbbc9b Vangelis Koukis
                # Assemble a TestSuite, and run it
1569 2aaa1336 John Giannelos
1570 2aaa1336 John Giannelos
                log_file = os.path.join(self.worker_folder, 'details_' +
1571 2aaa1336 John Giannelos
                                        (msg.__name__) + "_" +
1572 2aaa1336 John Giannelos
                                        TEST_RUN_ID + '.log')
1573 e50133da John Giannelos
1574 2aaa1336 John Giannelos
                fail_file = os.path.join(self.worker_folder, 'failed_' +
1575 2aaa1336 John Giannelos
                                         (msg.__name__) + "_" +
1576 2aaa1336 John Giannelos
                                         TEST_RUN_ID + '.log')
1577 2aaa1336 John Giannelos
                error_file = os.path.join(self.worker_folder, 'error_' +
1578 2aaa1336 John Giannelos
                                          (msg.__name__) + "_" +
1579 2aaa1336 John Giannelos
                                          TEST_RUN_ID + '.log')
1580 2aaa1336 John Giannelos
1581 2aaa1336 John Giannelos
                f = open(log_file, 'w')
1582 6e168615 Ilias Tsitsimpis
                fail = open(fail_file, 'w')
1583 2aaa1336 John Giannelos
                error = open(error_file, 'w')
1584 2aaa1336 John Giannelos
1585 2aaa1336 John Giannelos
                log.info(yellow + '* Starting testcase: %s' % msg + normal)
1586 2aaa1336 John Giannelos
1587 6e168615 Ilias Tsitsimpis
                runner = unittest.TextTestRunner(
1588 6e168615 Ilias Tsitsimpis
                    f, verbosity=2, failfast=True,
1589 6e168615 Ilias Tsitsimpis
                    resultclass=BurninTestResult)
1590 21bbbc9b Vangelis Koukis
                suite = unittest.TestLoader().loadTestsFromTestCase(msg)
1591 2aaa1336 John Giannelos
                result = runner.run(suite)
1592 2aaa1336 John Giannelos
1593 2aaa1336 John Giannelos
                for res in result.errors:
1594 6e168615 Ilias Tsitsimpis
                    log.error("snf-burnin encountered an error in "
1595 6e168615 Ilias Tsitsimpis
                              "testcase: %s" % msg)
1596 2aaa1336 John Giannelos
                    log.error("See log for details")
1597 2aaa1336 John Giannelos
                    error.write(str(res[0]) + '\n')
1598 2aaa1336 John Giannelos
                    error.write(str(res[0].shortDescription()) + '\n')
1599 2aaa1336 John Giannelos
                    error.write('\n')
1600 2aaa1336 John Giannelos
1601 2aaa1336 John Giannelos
                for res in result.failures:
1602 6e168615 Ilias Tsitsimpis
                    log.error("snf-burnin failed in testcase: %s" % msg)
1603 2aaa1336 John Giannelos
                    log.error("See log for details")
1604 2aaa1336 John Giannelos
                    fail.write(str(res[0]) + '\n')
1605 2aaa1336 John Giannelos
                    fail.write(str(res[0].shortDescription()) + '\n')
1606 2aaa1336 John Giannelos
                    fail.write('\n')
1607 6e168615 Ilias Tsitsimpis
                    if not NOFAILFAST:
1608 2aaa1336 John Giannelos
                        sys.exit()
1609 2aaa1336 John Giannelos
1610 2aaa1336 John Giannelos
                if (len(result.failures) == 0) and (len(result.errors) == 0):
1611 6e168615 Ilias Tsitsimpis
                    log.debug("Passed testcase: %s" % msg)
1612 2aaa1336 John Giannelos
1613 2aaa1336 John Giannelos
                f.close()
1614 2aaa1336 John Giannelos
                fail.close()
1615 2aaa1336 John Giannelos
                error.close()
1616 2aaa1336 John Giannelos
1617 21bbbc9b Vangelis Koukis
            else:
1618 21bbbc9b Vangelis Koukis
                raise Exception("Cannot handle msg: %s" % msg)
1619 21bbbc9b Vangelis Koukis
1620 6e168615 Ilias Tsitsimpis
1621 6e168615 Ilias Tsitsimpis
def _run_cases_in_series(cases, image_folder):
1622 3e4c5c32 John Giannelos
    """Run instances of TestCase in series"""
1623 3e4c5c32 John Giannelos
1624 3e4c5c32 John Giannelos
    for case in cases:
1625 3e4c5c32 John Giannelos
1626 3e4c5c32 John Giannelos
        test = case.__name__
1627 3e4c5c32 John Giannelos
1628 6e168615 Ilias Tsitsimpis
        log.info(yellow + '* Starting testcase: %s' % test + normal)
1629 3e4c5c32 John Giannelos
        log_file = os.path.join(image_folder, 'details_' +
1630 3e4c5c32 John Giannelos
                                (case.__name__) + "_" +
1631 3e4c5c32 John Giannelos
                                TEST_RUN_ID + '.log')
1632 3e4c5c32 John Giannelos
        fail_file = os.path.join(image_folder, 'failed_' +
1633 3e4c5c32 John Giannelos
                                 (case.__name__) + "_" +
1634 3e4c5c32 John Giannelos
                                 TEST_RUN_ID + '.log')
1635 3e4c5c32 John Giannelos
        error_file = os.path.join(image_folder, 'error_' +
1636 3e4c5c32 John Giannelos
                                  (case.__name__) + "_" +
1637 3e4c5c32 John Giannelos
                                  TEST_RUN_ID + '.log')
1638 3e4c5c32 John Giannelos
1639 3e4c5c32 John Giannelos
        f = open(log_file, "w")
1640 3e4c5c32 John Giannelos
        fail = open(fail_file, "w")
1641 3e4c5c32 John Giannelos
        error = open(error_file, "w")
1642 3e4c5c32 John Giannelos
1643 3e4c5c32 John Giannelos
        suite = unittest.TestLoader().loadTestsFromTestCase(case)
1644 6e168615 Ilias Tsitsimpis
        runner = unittest.TextTestRunner(
1645 6e168615 Ilias Tsitsimpis
            f, verbosity=2, failfast=True,
1646 6e168615 Ilias Tsitsimpis
            resultclass=BurninTestResult)
1647 3e4c5c32 John Giannelos
        result = runner.run(suite)
1648 3e4c5c32 John Giannelos
1649 3e4c5c32 John Giannelos
        for res in result.errors:
1650 6e168615 Ilias Tsitsimpis
            log.error("snf-burnin encountered an error in "
1651 6e168615 Ilias Tsitsimpis
                      "testcase: %s" % test)
1652 3e4c5c32 John Giannelos
            log.error("See log for details")
1653 3e4c5c32 John Giannelos
            error.write(str(res[0]) + '\n')
1654 3e4c5c32 John Giannelos
            error.write(str(res[0].shortDescription()) + '\n')
1655 3e4c5c32 John Giannelos
            error.write('\n')
1656 3e4c5c32 John Giannelos
1657 3e4c5c32 John Giannelos
        for res in result.failures:
1658 6e168615 Ilias Tsitsimpis
            log.error("snf-burnin failed in testcase: %s" % test)
1659 3e4c5c32 John Giannelos
            log.error("See log for details")
1660 3e4c5c32 John Giannelos
            fail.write(str(res[0]) + '\n')
1661 3e4c5c32 John Giannelos
            fail.write(str(res[0].shortDescription()) + '\n')
1662 3e4c5c32 John Giannelos
            fail.write('\n')
1663 6e168615 Ilias Tsitsimpis
            if not NOFAILFAST:
1664 3e4c5c32 John Giannelos
                sys.exit()
1665 3e4c5c32 John Giannelos
1666 3e4c5c32 John Giannelos
        if (len(result.failures) == 0) and (len(result.errors) == 0):
1667 6e168615 Ilias Tsitsimpis
            log.debug("Passed testcase: %s" % test)
1668 3e4c5c32 John Giannelos
1669 21bbbc9b Vangelis Koukis
1670 2aaa1336 John Giannelos
def _run_cases_in_parallel(cases, fanout, image_folder):
1671 21bbbc9b Vangelis Koukis
    """Run instances of TestCase in parallel, in a number of distinct processes
1672 21bbbc9b Vangelis Koukis

1673 21bbbc9b Vangelis Koukis
    The cases iterable specifies the TestCases to be executed in parallel,
1674 21bbbc9b Vangelis Koukis
    by test runners running in distinct processes.
1675 21bbbc9b Vangelis Koukis
    The fanout parameter specifies the number of processes to spawn,
1676 21bbbc9b Vangelis Koukis
    and defaults to 1.
1677 21bbbc9b Vangelis Koukis
    The runner argument specifies the test runner class to use inside each
1678 21bbbc9b Vangelis Koukis
    runner process.
1679 21bbbc9b Vangelis Koukis

1680 21bbbc9b Vangelis Koukis
    """
1681 e50133da John Giannelos
1682 2aaa1336 John Giannelos
    multi = logging.getLogger("multiprocess")
1683 2aaa1336 John Giannelos
    handler = logging.StreamHandler()
1684 2aaa1336 John Giannelos
    multi.addHandler(handler)
1685 21bbbc9b Vangelis Koukis
1686 2aaa1336 John Giannelos
    if VERBOSE:
1687 2aaa1336 John Giannelos
        multi.setLevel(logging.DEBUG)
1688 2aaa1336 John Giannelos
    else:
1689 2aaa1336 John Giannelos
        multi.setLevel(logging.INFO)
1690 2aaa1336 John Giannelos
1691 2aaa1336 John Giannelos
    testq = []
1692 2aaa1336 John Giannelos
    worker_folder = []
1693 21bbbc9b Vangelis Koukis
    runners = []
1694 2aaa1336 John Giannelos
1695 6e168615 Ilias Tsitsimpis
    for i in xrange(0, fanout):
1696 2aaa1336 John Giannelos
        testq.append(Queue())
1697 2aaa1336 John Giannelos
        worker_folder.append(os.path.join(image_folder, 'process'+str(i)))
1698 2aaa1336 John Giannelos
        os.mkdir(worker_folder[i])
1699 2aaa1336 John Giannelos
1700 21bbbc9b Vangelis Koukis
    for i in xrange(0, fanout):
1701 2aaa1336 John Giannelos
        kwargs = dict(testq=testq[i], worker_folder=worker_folder[i])
1702 21bbbc9b Vangelis Koukis
        runners.append(TestRunnerProcess(kwargs=kwargs))
1703 21bbbc9b Vangelis Koukis
1704 6e168615 Ilias Tsitsimpis
    multi.debug("Spawning %d test runner processes" % len(runners))
1705 2aaa1336 John Giannelos
1706 21bbbc9b Vangelis Koukis
    for p in runners:
1707 21bbbc9b Vangelis Koukis
        p.start()
1708 21bbbc9b Vangelis Koukis
1709 21bbbc9b Vangelis Koukis
    # Enqueue test cases
1710 2aaa1336 John Giannelos
    for i in xrange(0, fanout):
1711 2aaa1336 John Giannelos
        map(testq[i].put, cases)
1712 2aaa1336 John Giannelos
        testq[i].put("TEST_RUNNER_TERMINATE")
1713 2aaa1336 John Giannelos
1714 2aaa1336 John Giannelos
    multi.debug("Spawned %d test runners, PIDs are %s" %
1715 6e168615 Ilias Tsitsimpis
                (len(runners), [p.pid for p in runners]))
1716 21bbbc9b Vangelis Koukis
1717 2aaa1336 John Giannelos
    multi.debug("Joining %d processes" % len(runners))
1718 e50133da John Giannelos
1719 21bbbc9b Vangelis Koukis
    for p in runners:
1720 21bbbc9b Vangelis Koukis
        p.join()
1721 2aaa1336 John Giannelos
1722 2aaa1336 John Giannelos
    multi.debug("Done joining %d processes" % len(runners))
1723 4fdd25ab Vangelis Koukis
1724 5a140b23 Vangelis Koukis
1725 95a87099 Ilias Tsitsimpis
def _images_test_case(**kwargs):
1726 95a87099 Ilias Tsitsimpis
    """Construct a new unit test case class from ImagesTestCase"""
1727 95a87099 Ilias Tsitsimpis
    name = "ImagesTestCase_%s" % kwargs["imageid"]
1728 95a87099 Ilias Tsitsimpis
    cls = type(name, (ImagesTestCase,), kwargs)
1729 95a87099 Ilias Tsitsimpis
1730 95a87099 Ilias Tsitsimpis
    #Patch extra parameters into test names by manipulating method docstrings
1731 95a87099 Ilias Tsitsimpis
    for (mname, m) in \
1732 95a87099 Ilias Tsitsimpis
            inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
1733 95a87099 Ilias Tsitsimpis
        if hasattr(m, __doc__):
1734 95a87099 Ilias Tsitsimpis
            m.__func__.__doc__ = "[%s] %s" % (cls.imagename, m.__doc__)
1735 95a87099 Ilias Tsitsimpis
1736 95a87099 Ilias Tsitsimpis
    # Make sure the class can be pickled, by listing it among
1737 95a87099 Ilias Tsitsimpis
    # the attributes of __main__. A PicklingError is raised otherwise.
1738 95a87099 Ilias Tsitsimpis
    thismodule = sys.modules[__name__]
1739 95a87099 Ilias Tsitsimpis
    setattr(thismodule, name, cls)
1740 95a87099 Ilias Tsitsimpis
    return cls
1741 95a87099 Ilias Tsitsimpis
1742 95a87099 Ilias Tsitsimpis
1743 5a140b23 Vangelis Koukis
def _spawn_server_test_case(**kwargs):
1744 5a140b23 Vangelis Koukis
    """Construct a new unit test case class from SpawnServerTestCase"""
1745 5a140b23 Vangelis Koukis
1746 c1d11f96 John Giannelos
    name = "SpawnServerTestCase_%s" % kwargs["imageid"]
1747 5a140b23 Vangelis Koukis
    cls = type(name, (SpawnServerTestCase,), kwargs)
1748 5a140b23 Vangelis Koukis
1749 5a140b23 Vangelis Koukis
    # Patch extra parameters into test names by manipulating method docstrings
1750 5a140b23 Vangelis Koukis
    for (mname, m) in \
1751 6e168615 Ilias Tsitsimpis
            inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
1752 74ec726f John Giannelos
        if hasattr(m, __doc__):
1753 6e168615 Ilias Tsitsimpis
            m.__func__.__doc__ = "[%s] %s" % (cls.imagename, m.__doc__)
1754 e72bcf60 Vangelis Koukis
1755 e72bcf60 Vangelis Koukis
    # Make sure the class can be pickled, by listing it among
1756 e72bcf60 Vangelis Koukis
    # the attributes of __main__. A PicklingError is raised otherwise.
1757 2aaa1336 John Giannelos
1758 2aaa1336 John Giannelos
    thismodule = sys.modules[__name__]
1759 2aaa1336 John Giannelos
    setattr(thismodule, name, cls)
1760 8252d64f John Giannelos
    return cls
1761 65462ca9 John Giannelos
1762 2bcfb712 John Giannelos
1763 65462ca9 John Giannelos
def _spawn_network_test_case(**kwargs):
1764 65462ca9 John Giannelos
    """Construct a new unit test case class from NetworkTestCase"""
1765 65462ca9 John Giannelos
1766 2bcfb712 John Giannelos
    name = "NetworkTestCase" + TEST_RUN_ID
1767 65462ca9 John Giannelos
    cls = type(name, (NetworkTestCase,), kwargs)
1768 65462ca9 John Giannelos
1769 65462ca9 John Giannelos
    # Make sure the class can be pickled, by listing it among
1770 65462ca9 John Giannelos
    # the attributes of __main__. A PicklingError is raised otherwise.
1771 e50133da John Giannelos
1772 2aaa1336 John Giannelos
    thismodule = sys.modules[__name__]
1773 2aaa1336 John Giannelos
    setattr(thismodule, name, cls)
1774 8252d64f John Giannelos
    return cls
1775 5a140b23 Vangelis Koukis
1776 5a140b23 Vangelis Koukis
1777 8792bb97 Ilias Tsitsimpis
# --------------------------------------------------------------------
1778 8792bb97 Ilias Tsitsimpis
# Clean up servers/networks functions
1779 c0448f4f John Giannelos
def cleanup_servers(timeout, query_interval, delete_stale=False):
1780 74193008 John Giannelos
1781 567ffb85 John Giannelos
    c = ComputeClient(API, TOKEN)
1782 74193008 John Giannelos
1783 5a140b23 Vangelis Koukis
    servers = c.list_servers()
1784 5a140b23 Vangelis Koukis
    stale = [s for s in servers if s["name"].startswith(SNF_TEST_PREFIX)]
1785 5a140b23 Vangelis Koukis
1786 4fdd25ab Vangelis Koukis
    if len(stale) == 0:
1787 4fdd25ab Vangelis Koukis
        return
1788 4fdd25ab Vangelis Koukis
1789 8792bb97 Ilias Tsitsimpis
    # Show staled servers
1790 8792bb97 Ilias Tsitsimpis
    print >>sys.stderr, yellow + \
1791 6e168615 Ilias Tsitsimpis
        "Found these stale servers from previous runs:" + \
1792 6e168615 Ilias Tsitsimpis
        normal
1793 8792bb97 Ilias Tsitsimpis
    print >>sys.stderr, "    " + \
1794 6e168615 Ilias Tsitsimpis
        "\n    ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
1795 5a140b23 Vangelis Koukis
1796 8792bb97 Ilias Tsitsimpis
    # Delete staled servers
1797 5a140b23 Vangelis Koukis
    if delete_stale:
1798 5a140b23 Vangelis Koukis
        print >> sys.stderr, "Deleting %d stale servers:" % len(stale)
1799 c0448f4f John Giannelos
        fail_tmout = time.time() + timeout
1800 c0448f4f John Giannelos
        for s in stale:
1801 c0448f4f John Giannelos
            c.delete_server(s["id"])
1802 8792bb97 Ilias Tsitsimpis
        # Wait for all servers to be deleted
1803 c0448f4f John Giannelos
        while True:
1804 c0448f4f John Giannelos
            servers = c.list_servers()
1805 6e168615 Ilias Tsitsimpis
            stale = [s for s in servers
1806 6e168615 Ilias Tsitsimpis
                     if s["name"].startswith(SNF_TEST_PREFIX)]
1807 6e168615 Ilias Tsitsimpis
            if len(stale) == 0:
1808 c0448f4f John Giannelos
                print >> sys.stderr, green + "    ...done" + normal
1809 c0448f4f John Giannelos
                break
1810 c0448f4f John Giannelos
            elif time.time() > fail_tmout:
1811 8792bb97 Ilias Tsitsimpis
                print >> sys.stderr, red + \
1812 6e168615 Ilias Tsitsimpis
                    "Not all stale servers deleted. Action timed out." + \
1813 6e168615 Ilias Tsitsimpis
                    normal
1814 6e168615 Ilias Tsitsimpis
                sys.exit(1)
1815 c0448f4f John Giannelos
            else:
1816 c0448f4f John Giannelos
                time.sleep(query_interval)
1817 5a140b23 Vangelis Koukis
    else:
1818 5a140b23 Vangelis Koukis
        print >> sys.stderr, "Use --delete-stale to delete them."
1819 5a140b23 Vangelis Koukis
1820 2bcfb712 John Giannelos
1821 f752215c John Giannelos
def cleanup_networks(action_timeout, query_interval, delete_stale=False):
1822 74ec726f John Giannelos
1823 74ec726f John Giannelos
    c = CycladesClient(API, TOKEN)
1824 e50133da John Giannelos
1825 74ec726f John Giannelos
    networks = c.list_networks()
1826 74ec726f John Giannelos
    stale = [n for n in networks if n["name"].startswith(SNF_TEST_PREFIX)]
1827 74ec726f John Giannelos
1828 74ec726f John Giannelos
    if len(stale) == 0:
1829 74ec726f John Giannelos
        return
1830 e50133da John Giannelos
1831 8792bb97 Ilias Tsitsimpis
    # Show staled networks
1832 8792bb97 Ilias Tsitsimpis
    print >> sys.stderr, yellow + \
1833 6e168615 Ilias Tsitsimpis
        "Found these stale networks from previous runs:" + \
1834 6e168615 Ilias Tsitsimpis
        normal
1835 74ec726f John Giannelos
    print "    " + \
1836 6e168615 Ilias Tsitsimpis
        "\n    ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
1837 74ec726f John Giannelos
1838 8792bb97 Ilias Tsitsimpis
    # Delete staled networks
1839 74ec726f John Giannelos
    if delete_stale:
1840 74ec726f John Giannelos
        print >> sys.stderr, "Deleting %d stale networks:" % len(stale)
1841 f752215c John Giannelos
        fail_tmout = time.time() + action_timeout
1842 c0448f4f John Giannelos
        for n in stale:
1843 c0448f4f John Giannelos
            c.delete_network(n["id"])
1844 8792bb97 Ilias Tsitsimpis
        # Wait for all networks to be deleted
1845 c0448f4f John Giannelos
        while True:
1846 c0448f4f John Giannelos
            networks = c.list_networks()
1847 6e168615 Ilias Tsitsimpis
            stale = [n for n in networks
1848 6e168615 Ilias Tsitsimpis
                     if n["name"].startswith(SNF_TEST_PREFIX)]
1849 6e168615 Ilias Tsitsimpis
            if len(stale) == 0:
1850 c0448f4f John Giannelos
                print >> sys.stderr, green + "    ...done" + normal
1851 c0448f4f John Giannelos
                break
1852 c0448f4f John Giannelos
            elif time.time() > fail_tmout:
1853 8792bb97 Ilias Tsitsimpis
                print >> sys.stderr, red + \
1854 6e168615 Ilias Tsitsimpis
                    "Not all stale networks deleted. Action timed out." + \
1855 6e168615 Ilias Tsitsimpis
                    normal
1856 6e168615 Ilias Tsitsimpis
                sys.exit(1)
1857 c0448f4f John Giannelos
            else:
1858 c0448f4f John Giannelos
                time.sleep(query_interval)
1859 74ec726f John Giannelos
    else:
1860 74ec726f John Giannelos
        print >> sys.stderr, "Use --delete-stale to delete them."
1861 74ec726f John Giannelos
1862 746540cd John Giannelos
1863 8792bb97 Ilias Tsitsimpis
# --------------------------------------------------------------------
1864 8792bb97 Ilias Tsitsimpis
# Parse arguments functions
1865 22efe1fe John Giannelos
def parse_comma(option, opt, value, parser):
1866 746540cd John Giannelos
    tests = set(['all', 'auth', 'images', 'flavors',
1867 11779b6c Ilias Tsitsimpis
                 'pithos', 'servers', 'server_spawn',
1868 11779b6c Ilias Tsitsimpis
                 'network_spawn'])
1869 22efe1fe John Giannelos
    parse_input = value.split(',')
1870 22efe1fe John Giannelos
1871 22efe1fe John Giannelos
    if not (set(parse_input)).issubset(tests):
1872 22efe1fe John Giannelos
        raise OptionValueError("The selected set of tests is invalid")
1873 22efe1fe John Giannelos
1874 22efe1fe John Giannelos
    setattr(parser.values, option.dest, value.split(','))
1875 22efe1fe John Giannelos
1876 74ec726f John Giannelos
1877 5a140b23 Vangelis Koukis
def parse_arguments(args):
1878 5a140b23 Vangelis Koukis
1879 5a140b23 Vangelis Koukis
    kw = {}
1880 5a140b23 Vangelis Koukis
    kw["usage"] = "%prog [options]"
1881 5a140b23 Vangelis Koukis
    kw["description"] = \
1882 5a140b23 Vangelis Koukis
        "%prog runs a number of test scenarios on a " \
1883 5a140b23 Vangelis Koukis
        "Synnefo deployment."
1884 5a140b23 Vangelis Koukis
1885 5a140b23 Vangelis Koukis
    parser = OptionParser(**kw)
1886 5a140b23 Vangelis Koukis
    parser.disable_interspersed_args()
1887 22efe1fe John Giannelos
1888 21bbbc9b Vangelis Koukis
    parser.add_option("--api",
1889 21bbbc9b Vangelis Koukis
                      action="store", type="string", dest="api",
1890 21bbbc9b Vangelis Koukis
                      help="The API URI to use to reach the Synnefo API",
1891 11779b6c Ilias Tsitsimpis
                      default=None)
1892 946da8b6 John Giannelos
    parser.add_option("--plankton",
1893 946da8b6 John Giannelos
                      action="store", type="string", dest="plankton",
1894 946da8b6 John Giannelos
                      help="The API URI to use to reach the Plankton API",
1895 11779b6c Ilias Tsitsimpis
                      default=None)
1896 946da8b6 John Giannelos
    parser.add_option("--plankton-user",
1897 946da8b6 John Giannelos
                      action="store", type="string", dest="plankton_user",
1898 946da8b6 John Giannelos
                      help="Owner of system images",
1899 946da8b6 John Giannelos
                      default=DEFAULT_PLANKTON_USER)
1900 11779b6c Ilias Tsitsimpis
    parser.add_option("--pithos",
1901 11779b6c Ilias Tsitsimpis
                      action="store", type="string", dest="pithos",
1902 11779b6c Ilias Tsitsimpis
                      help="The API URI to use to reach the Pithos API",
1903 11779b6c Ilias Tsitsimpis
                      default=None)
1904 bacb7c87 Ilias Tsitsimpis
    parser.add_option("--astakos",
1905 bacb7c87 Ilias Tsitsimpis
                      action="store", type="string", dest="astakos",
1906 bacb7c87 Ilias Tsitsimpis
                      help="The API URI to use to reach the Astakos API",
1907 11779b6c Ilias Tsitsimpis
                      default=None)
1908 21bbbc9b Vangelis Koukis
    parser.add_option("--token",
1909 21bbbc9b Vangelis Koukis
                      action="store", type="string", dest="token",
1910 38d247df Kostas Papadimitriou
                      help="The token to use for authentication to the API")
1911 00f87624 Vangelis Koukis
    parser.add_option("--nofailfast",
1912 00f87624 Vangelis Koukis
                      action="store_true", dest="nofailfast",
1913 6e168615 Ilias Tsitsimpis
                      help="Do not fail immediately if one of the tests "
1914 00f87624 Vangelis Koukis
                           "fails (EXPERIMENTAL)",
1915 bc14ba88 Vangelis Koukis
                      default=False)
1916 946da8b6 John Giannelos
    parser.add_option("--no-ipv6",
1917 946da8b6 John Giannelos
                      action="store_true", dest="no_ipv6",
1918 946da8b6 John Giannelos
                      help="Disables ipv6 related tests",
1919 946da8b6 John Giannelos
                      default=False)
1920 5a140b23 Vangelis Koukis
    parser.add_option("--action-timeout",
1921 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="action_timeout",
1922 5a140b23 Vangelis Koukis
                      metavar="TIMEOUT",
1923 6e168615 Ilias Tsitsimpis
                      help="Wait SECONDS seconds for a server action to "
1924 5a140b23 Vangelis Koukis
                           "complete, then the test is considered failed",
1925 9e4682b5 John Giannelos
                      default=100)
1926 5a140b23 Vangelis Koukis
    parser.add_option("--build-warning",
1927 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="build_warning",
1928 5a140b23 Vangelis Koukis
                      metavar="TIMEOUT",
1929 6e168615 Ilias Tsitsimpis
                      help="Warn if TIMEOUT seconds have passed and a "
1930 5a140b23 Vangelis Koukis
                           "build operation is still pending",
1931 5a140b23 Vangelis Koukis
                      default=600)
1932 5a140b23 Vangelis Koukis
    parser.add_option("--build-fail",
1933 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="build_fail",
1934 5a140b23 Vangelis Koukis
                      metavar="BUILD_TIMEOUT",
1935 6e168615 Ilias Tsitsimpis
                      help="Fail the test if TIMEOUT seconds have passed "
1936 5a140b23 Vangelis Koukis
                           "and a build operation is still incomplete",
1937 5a140b23 Vangelis Koukis
                      default=900)
1938 5a140b23 Vangelis Koukis
    parser.add_option("--query-interval",
1939 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="query_interval",
1940 5a140b23 Vangelis Koukis
                      metavar="INTERVAL",
1941 6e168615 Ilias Tsitsimpis
                      help="Query server status when requests are pending "
1942 5a140b23 Vangelis Koukis
                           "every INTERVAL seconds",
1943 5a140b23 Vangelis Koukis
                      default=3)
1944 21bbbc9b Vangelis Koukis
    parser.add_option("--fanout",
1945 21bbbc9b Vangelis Koukis
                      action="store", type="int", dest="fanout",
1946 5a140b23 Vangelis Koukis
                      metavar="COUNT",
1947 6e168615 Ilias Tsitsimpis
                      help="Spawn up to COUNT child processes to execute "
1948 6e168615 Ilias Tsitsimpis
                           "in parallel, essentially have up to COUNT "
1949 00f87624 Vangelis Koukis
                           "server build requests outstanding (EXPERIMENTAL)",
1950 5a140b23 Vangelis Koukis
                      default=1)
1951 5a140b23 Vangelis Koukis
    parser.add_option("--force-flavor",
1952 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="force_flavorid",
1953 5a140b23 Vangelis Koukis
                      metavar="FLAVOR ID",
1954 6e168615 Ilias Tsitsimpis
                      help="Force all server creations to use the specified "
1955 6e168615 Ilias Tsitsimpis
                           "FLAVOR ID instead of a randomly chosen one, "
1956 5a140b23 Vangelis Koukis
                           "useful if disk space is scarce",
1957 00f87624 Vangelis Koukis
                      default=None)
1958 7f62a0b5 Vangelis Koukis
    parser.add_option("--image-id",
1959 7f62a0b5 Vangelis Koukis
                      action="store", type="string", dest="force_imageid",
1960 00f87624 Vangelis Koukis
                      metavar="IMAGE ID",
1961 6e168615 Ilias Tsitsimpis
                      help="Test the specified image id, use 'all' to test "
1962 7f62a0b5 Vangelis Koukis
                           "all available images (mandatory argument)",
1963 00f87624 Vangelis Koukis
                      default=None)
1964 5a140b23 Vangelis Koukis
    parser.add_option("--show-stale",
1965 5a140b23 Vangelis Koukis
                      action="store_true", dest="show_stale",
1966 6e168615 Ilias Tsitsimpis
                      help="Show stale servers from previous runs, whose "
1967 21bbbc9b Vangelis Koukis
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1968 5a140b23 Vangelis Koukis
                      default=False)
1969 5a140b23 Vangelis Koukis
    parser.add_option("--delete-stale",
1970 5a140b23 Vangelis Koukis
                      action="store_true", dest="delete_stale",
1971 6e168615 Ilias Tsitsimpis
                      help="Delete stale servers from previous runs, whose "
1972 21bbbc9b Vangelis Koukis
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1973 5a140b23 Vangelis Koukis
                      default=False)
1974 9659e075 John Giannelos
    parser.add_option("--force-personality",
1975 65462ca9 John Giannelos
                      action="store", type="string", dest="personality_path",
1976 8252d64f John Giannelos
                      help="Force a personality file injection.\
1977 8252d64f John Giannelos
                            File path required. ",
1978 9659e075 John Giannelos
                      default=None)
1979 74ec726f John Giannelos
    parser.add_option("--log-folder",
1980 74ec726f John Giannelos
                      action="store", type="string", dest="log_folder",
1981 8252d64f John Giannelos
                      help="Define the absolute path where the output \
1982 8252d64f John Giannelos
                            log is stored. ",
1983 2bcfb712 John Giannelos
                      default="/var/log/burnin/")
1984 2aaa1336 John Giannelos
    parser.add_option("--verbose", "-V",
1985 2aaa1336 John Giannelos
                      action="store_true", dest="verbose",
1986 6e168615 Ilias Tsitsimpis
                      help="Print detailed output about multiple "
1987 8792bb97 Ilias Tsitsimpis
                           "processes spawning",
1988 2aaa1336 John Giannelos
                      default=False)
1989 22efe1fe John Giannelos
    parser.add_option("--set-tests",
1990 22efe1fe John Giannelos
                      action="callback",
1991 746540cd John Giannelos
                      dest="tests",
1992 22efe1fe John Giannelos
                      type="string",
1993 22efe1fe John Giannelos
                      help='Set comma seperated tests for this run. \
1994 22efe1fe John Giannelos
                            Available tests: auth, images, flavors, \
1995 746540cd John Giannelos
                                             servers, server_spawn, \
1996 11779b6c Ilias Tsitsimpis
                                             network_spawn, pithos. \
1997 22efe1fe John Giannelos
                            Default = all',
1998 22efe1fe John Giannelos
                      default='all',
1999 22efe1fe John Giannelos
                      callback=parse_comma)
2000 22efe1fe John Giannelos
2001 5a140b23 Vangelis Koukis
    (opts, args) = parser.parse_args(args)
2002 5a140b23 Vangelis Koukis
2003 8792bb97 Ilias Tsitsimpis
    # -----------------------
2004 5a140b23 Vangelis Koukis
    # Verify arguments
2005 8792bb97 Ilias Tsitsimpis
2006 8792bb97 Ilias Tsitsimpis
    # `delete_stale' implies `show_stale'
2007 5a140b23 Vangelis Koukis
    if opts.delete_stale:
2008 5a140b23 Vangelis Koukis
        opts.show_stale = True
2009 5a140b23 Vangelis Koukis
2010 11779b6c Ilias Tsitsimpis
    # `token' is mandatory
2011 11779b6c Ilias Tsitsimpis
    _mandatory_argument(opts.token, "--token")
2012 11779b6c Ilias Tsitsimpis
    # `api' is mandatory
2013 11779b6c Ilias Tsitsimpis
    _mandatory_argument(opts.api, "--api")
2014 11779b6c Ilias Tsitsimpis
2015 7f62a0b5 Vangelis Koukis
    if not opts.show_stale:
2016 11779b6c Ilias Tsitsimpis
        # `image-id' is mandatory
2017 11779b6c Ilias Tsitsimpis
        _mandatory_argument(opts.force_imageid, "--image_id")
2018 7f62a0b5 Vangelis Koukis
        if opts.force_imageid != 'all':
2019 7f62a0b5 Vangelis Koukis
            try:
2020 99d41650 John Giannelos
                opts.force_imageid = str(opts.force_imageid)
2021 7f62a0b5 Vangelis Koukis
            except ValueError:
2022 8792bb97 Ilias Tsitsimpis
                print >>sys.stderr, red + \
2023 6e168615 Ilias Tsitsimpis
                    "Invalid value specified for" + \
2024 6e168615 Ilias Tsitsimpis
                    "--image-id. Use a valid id, or `all'." + \
2025 6e168615 Ilias Tsitsimpis
                    normal
2026 7f62a0b5 Vangelis Koukis
                sys.exit(1)
2027 11779b6c Ilias Tsitsimpis
        # `pithos' is mandatory
2028 11779b6c Ilias Tsitsimpis
        _mandatory_argument(opts.pithos, "--pithos")
2029 bacb7c87 Ilias Tsitsimpis
        # `astakos' is mandatory
2030 bacb7c87 Ilias Tsitsimpis
        _mandatory_argument(opts.astakos, "--astakos")
2031 11779b6c Ilias Tsitsimpis
        # `plankton' is mandatory
2032 11779b6c Ilias Tsitsimpis
        _mandatory_argument(opts.plankton, "--plankton")
2033 7f62a0b5 Vangelis Koukis
2034 11779b6c Ilias Tsitsimpis
    return (opts, args)
2035 11779b6c Ilias Tsitsimpis
2036 11779b6c Ilias Tsitsimpis
2037 11779b6c Ilias Tsitsimpis
def _mandatory_argument(Arg, Str):
2038 11779b6c Ilias Tsitsimpis
    if not Arg:
2039 8792bb97 Ilias Tsitsimpis
        print >>sys.stderr, red + \
2040 11779b6c Ilias Tsitsimpis
            "The " + Str + " argument is mandatory.\n" + \
2041 6e168615 Ilias Tsitsimpis
            normal
2042 8792bb97 Ilias Tsitsimpis
        sys.exit(1)
2043 8792bb97 Ilias Tsitsimpis
2044 5a140b23 Vangelis Koukis
2045 8792bb97 Ilias Tsitsimpis
# --------------------------------------------------------------------
2046 8792bb97 Ilias Tsitsimpis
# Burnin main function
2047 5a140b23 Vangelis Koukis
def main():
2048 5a140b23 Vangelis Koukis
    """Assemble test cases into a test suite, and run it
2049 5a140b23 Vangelis Koukis

2050 5a140b23 Vangelis Koukis
    IMPORTANT: Tests have dependencies and have to be run in the specified
2051 5a140b23 Vangelis Koukis
    order inside a single test case. They communicate through attributes of the
2052 21bbbc9b Vangelis Koukis
    corresponding TestCase class (shared fixtures). Distinct subclasses of
2053 21bbbc9b Vangelis Koukis
    TestCase MAY SHARE NO DATA, since they are run in parallel, in distinct
2054 21bbbc9b Vangelis Koukis
    test runner processes.
2055 5a140b23 Vangelis Koukis

2056 5a140b23 Vangelis Koukis
    """
2057 ae139e8a John Giannelos
2058 8792bb97 Ilias Tsitsimpis
    # Parse arguments using `optparse'
2059 5a140b23 Vangelis Koukis
    (opts, args) = parse_arguments(sys.argv[1:])
2060 5a140b23 Vangelis Koukis
2061 8792bb97 Ilias Tsitsimpis
    # Some global variables
2062 11779b6c Ilias Tsitsimpis
    global API, TOKEN, PLANKTON, PLANKTON_USER
2063 bacb7c87 Ilias Tsitsimpis
    global PITHOS, ASTAKOS, NO_IPV6, VERBOSE, NOFAILFAST
2064 21bbbc9b Vangelis Koukis
    API = opts.api
2065 21bbbc9b Vangelis Koukis
    TOKEN = opts.token
2066 946da8b6 John Giannelos
    PLANKTON = opts.plankton
2067 946da8b6 John Giannelos
    PLANKTON_USER = opts.plankton_user
2068 11779b6c Ilias Tsitsimpis
    PITHOS = opts.pithos
2069 bacb7c87 Ilias Tsitsimpis
    ASTAKOS = opts.astakos
2070 946da8b6 John Giannelos
    NO_IPV6 = opts.no_ipv6
2071 2aaa1336 John Giannelos
    VERBOSE = opts.verbose
2072 2aaa1336 John Giannelos
    NOFAILFAST = opts.nofailfast
2073 21bbbc9b Vangelis Koukis
2074 8792bb97 Ilias Tsitsimpis
    # If `show_stale', cleanup stale servers
2075 8792bb97 Ilias Tsitsimpis
    # from previous runs and exit
2076 5a140b23 Vangelis Koukis
    if opts.show_stale:
2077 8792bb97 Ilias Tsitsimpis
        # We must clean the servers first
2078 8792bb97 Ilias Tsitsimpis
        cleanup_servers(opts.action_timeout, opts.query_interval,
2079 8792bb97 Ilias Tsitsimpis
                        delete_stale=opts.delete_stale)
2080 8792bb97 Ilias Tsitsimpis
        cleanup_networks(opts.action_timeout, opts.query_interval,
2081 8792bb97 Ilias Tsitsimpis
                         delete_stale=opts.delete_stale)
2082 74ec726f John Giannelos
        return 0
2083 5a140b23 Vangelis Koukis
2084 5a140b23 Vangelis Koukis
    # Initialize a kamaki instance, get flavors, images
2085 96da37c8 John Giannelos
    c = ComputeClient(API, TOKEN)
2086 5a140b23 Vangelis Koukis
    DIMAGES = c.list_images(detail=True)
2087 5a140b23 Vangelis Koukis
    DFLAVORS = c.list_flavors(detail=True)
2088 5a140b23 Vangelis Koukis
2089 21bbbc9b Vangelis Koukis
    # FIXME: logging, log, LOG PID, TEST_RUN_ID, arguments
2090 5a140b23 Vangelis Koukis
    # Run them: FIXME: In parallel, FAILEARLY, catchbreak?
2091 5a140b23 Vangelis Koukis
    #unittest.main(verbosity=2, catchbreak=True)
2092 5a140b23 Vangelis Koukis
2093 6e168615 Ilias Tsitsimpis
    # Get a list of images we are going to test
2094 e94a9d8c John Giannelos
    if opts.force_imageid == 'all':
2095 e94a9d8c John Giannelos
        test_images = DIMAGES
2096 e94a9d8c John Giannelos
    else:
2097 e94a9d8c John Giannelos
        test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
2098 e94a9d8c John Giannelos
2099 6e168615 Ilias Tsitsimpis
    # Create output (logging) folder
2100 74ec726f John Giannelos
    if not os.path.exists(opts.log_folder):
2101 74ec726f John Giannelos
        os.mkdir(opts.log_folder)
2102 2bcfb712 John Giannelos
    test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
2103 74ec726f John Giannelos
    os.mkdir(test_folder)
2104 81e8cbf6 John Giannelos
2105 00f87624 Vangelis Koukis
    for image in test_images:
2106 99d41650 John Giannelos
        imageid = str(image["id"])
2107 6e168615 Ilias Tsitsimpis
        imagename = image["name"]
2108 6e168615 Ilias Tsitsimpis
        # Choose a flavor (given from user or random)
2109 81e8cbf6 John Giannelos
        if opts.force_flavorid:
2110 81e8cbf6 John Giannelos
            flavorid = opts.force_flavorid
2111 81e8cbf6 John Giannelos
        else:
2112 81e8cbf6 John Giannelos
            flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
2113 6e168615 Ilias Tsitsimpis
        # Personality dictionary for file injection test
2114 6e168615 Ilias Tsitsimpis
        if opts.personality_path is not None:
2115 9659e075 John Giannelos
            f = open(opts.personality_path)
2116 9659e075 John Giannelos
            content = b64encode(f.read())
2117 9659e075 John Giannelos
            personality = []
2118 9659e075 John Giannelos
            st = os.stat(opts.personality_path)
2119 9659e075 John Giannelos
            personality.append({
2120 6e168615 Ilias Tsitsimpis
                'path': '/root/test_inj_file',
2121 6e168615 Ilias Tsitsimpis
                'owner': 'root',
2122 6e168615 Ilias Tsitsimpis
                'group': 'root',
2123 6e168615 Ilias Tsitsimpis
                'mode': 0x7777 & st.st_mode,
2124 6e168615 Ilias Tsitsimpis
                'contents': content})
2125 9659e075 John Giannelos
        else:
2126 9659e075 John Giannelos
            personality = None
2127 6e168615 Ilias Tsitsimpis
        # Give a name to our test servers
2128 21bbbc9b Vangelis Koukis
        servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
2129 21bbbc9b Vangelis Koukis
        is_windows = imagename.lower().find("windows") >= 0
2130 8252d64f John Giannelos
2131 6e168615 Ilias Tsitsimpis
        # Create Server TestCases
2132 8252d64f John Giannelos
        ServerTestCase = _spawn_server_test_case(
2133 8252d64f John Giannelos
            imageid=imageid,
2134 8252d64f John Giannelos
            flavorid=flavorid,
2135 8252d64f John Giannelos
            imagename=imagename,
2136 8252d64f John Giannelos
            personality=personality,
2137 8252d64f John Giannelos
            servername=servername,
2138 8252d64f John Giannelos
            is_windows=is_windows,
2139 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
2140 8252d64f John Giannelos
            build_warning=opts.build_warning,
2141 8252d64f John Giannelos
            build_fail=opts.build_fail,
2142 6e168615 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2143 6e168615 Ilias Tsitsimpis
        # Create Network TestCases
2144 8252d64f John Giannelos
        NetworkTestCase = _spawn_network_test_case(
2145 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
2146 8252d64f John Giannelos
            imageid=imageid,
2147 8252d64f John Giannelos
            flavorid=flavorid,
2148 8252d64f John Giannelos
            imagename=imagename,
2149 6e168615 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2150 95a87099 Ilias Tsitsimpis
        # Create Images TestCase
2151 95a87099 Ilias Tsitsimpis
        CImagesTestCase = _images_test_case(
2152 95a87099 Ilias Tsitsimpis
            action_timeout=opts.action_timeout,
2153 95a87099 Ilias Tsitsimpis
            imageid=imageid,
2154 95a87099 Ilias Tsitsimpis
            flavorid=flavorid,
2155 95a87099 Ilias Tsitsimpis
            imagename=imagename,
2156 95a87099 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2157 8252d64f John Giannelos
2158 6e168615 Ilias Tsitsimpis
        # Choose the tests we are going to run
2159 746540cd John Giannelos
        test_dict = {'auth': UnauthorizedTestCase,
2160 95a87099 Ilias Tsitsimpis
                     'images': CImagesTestCase,
2161 746540cd John Giannelos
                     'flavors': FlavorsTestCase,
2162 746540cd John Giannelos
                     'servers': ServersTestCase,
2163 11779b6c Ilias Tsitsimpis
                     'pithos': PithosTestCase,
2164 746540cd John Giannelos
                     'server_spawn': ServerTestCase,
2165 746540cd John Giannelos
                     'network_spawn': NetworkTestCase}
2166 22efe1fe John Giannelos
        seq_cases = []
2167 22efe1fe John Giannelos
        if 'all' in opts.tests:
2168 4d72f9ab Ilias Tsitsimpis
            seq_cases = [UnauthorizedTestCase, CImagesTestCase,
2169 11779b6c Ilias Tsitsimpis
                         FlavorsTestCase, ServersTestCase,
2170 11779b6c Ilias Tsitsimpis
                         PithosTestCase, ServerTestCase,
2171 11779b6c Ilias Tsitsimpis
                         NetworkTestCase]
2172 22efe1fe John Giannelos
        else:
2173 22efe1fe John Giannelos
            for test in opts.tests:
2174 22efe1fe John Giannelos
                seq_cases.append(test_dict[test])
2175 22efe1fe John Giannelos
2176 6e168615 Ilias Tsitsimpis
        # Folder for each image
2177 2bcfb712 John Giannelos
        image_folder = os.path.join(test_folder, imageid)
2178 81e8cbf6 John Giannelos
        os.mkdir(image_folder)
2179 81e8cbf6 John Giannelos
2180 6e168615 Ilias Tsitsimpis
        # Run each test
2181 6e168615 Ilias Tsitsimpis
        if opts.fanout > 1:
2182 3e4c5c32 John Giannelos
            _run_cases_in_parallel(seq_cases, opts.fanout, image_folder)
2183 3e4c5c32 John Giannelos
        else:
2184 6e168615 Ilias Tsitsimpis
            _run_cases_in_series(seq_cases, image_folder)
2185 6e168615 Ilias Tsitsimpis
2186 746540cd John Giannelos
2187 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
2188 6e168615 Ilias Tsitsimpis
# Call main
2189 5a140b23 Vangelis Koukis
if __name__ == "__main__":
2190 5a140b23 Vangelis Koukis
    sys.exit(main())