Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin.py @ 33d1cf90

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

810 f752215c John Giannelos
        Implementation of RFB protocol follows
811 f752215c John Giannelos
        http://www.realvnc.com/docs/rfbproto.pdf.
812 bc14ba88 Vangelis Koukis

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

1728 21bbbc9b Vangelis Koukis
    The cases iterable specifies the TestCases to be executed in parallel,
1729 21bbbc9b Vangelis Koukis
    by test runners running in distinct processes.
1730 21bbbc9b Vangelis Koukis
    The fanout parameter specifies the number of processes to spawn,
1731 21bbbc9b Vangelis Koukis
    and defaults to 1.
1732 21bbbc9b Vangelis Koukis
    The runner argument specifies the test runner class to use inside each
1733 21bbbc9b Vangelis Koukis
    runner process.
1734 21bbbc9b Vangelis Koukis

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

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

2105 5a140b23 Vangelis Koukis
    """
2106 ae139e8a John Giannelos
2107 8792bb97 Ilias Tsitsimpis
    # Parse arguments using `optparse'
2108 5a140b23 Vangelis Koukis
    (opts, args) = parse_arguments(sys.argv[1:])
2109 5a140b23 Vangelis Koukis
2110 8792bb97 Ilias Tsitsimpis
    # Some global variables
2111 33d1cf90 Ilias Tsitsimpis
    global AUTH_URL, TOKEN, SYSTEM_IMAGES_USER
2112 186428b0 Ilias Tsitsimpis
    global NO_IPV6, VERBOSE, NOFAILFAST
2113 186428b0 Ilias Tsitsimpis
    AUTH_URL = opts.auth_url
2114 21bbbc9b Vangelis Koukis
    TOKEN = opts.token
2115 33d1cf90 Ilias Tsitsimpis
    SYSTEM_IMAGES_USER = opts.system_images_user
2116 946da8b6 John Giannelos
    NO_IPV6 = opts.no_ipv6
2117 2aaa1336 John Giannelos
    VERBOSE = opts.verbose
2118 2aaa1336 John Giannelos
    NOFAILFAST = opts.nofailfast
2119 21bbbc9b Vangelis Koukis
2120 8792bb97 Ilias Tsitsimpis
    # If `show_stale', cleanup stale servers
2121 8792bb97 Ilias Tsitsimpis
    # from previous runs and exit
2122 5a140b23 Vangelis Koukis
    if opts.show_stale:
2123 8792bb97 Ilias Tsitsimpis
        # We must clean the servers first
2124 8792bb97 Ilias Tsitsimpis
        cleanup_servers(opts.action_timeout, opts.query_interval,
2125 8792bb97 Ilias Tsitsimpis
                        delete_stale=opts.delete_stale)
2126 8792bb97 Ilias Tsitsimpis
        cleanup_networks(opts.action_timeout, opts.query_interval,
2127 8792bb97 Ilias Tsitsimpis
                         delete_stale=opts.delete_stale)
2128 74ec726f John Giannelos
        return 0
2129 5a140b23 Vangelis Koukis
2130 5a140b23 Vangelis Koukis
    # Initialize a kamaki instance, get flavors, images
2131 186428b0 Ilias Tsitsimpis
    astakos_client = AstakosClient(AUTH_URL, TOKEN)
2132 89af2bbd Ilias Tsitsimpis
    astakos_client.CONNECTION_RETRY_LIMIT = 2
2133 186428b0 Ilias Tsitsimpis
    # Compute Client
2134 186428b0 Ilias Tsitsimpis
    compute_url = astakos_client.get_service_endpoints('compute')['publicURL']
2135 186428b0 Ilias Tsitsimpis
    compute_client = ComputeClient(compute_url, TOKEN)
2136 89af2bbd Ilias Tsitsimpis
    compute_client.CONNECTION_RETRY_LIMIT = 2
2137 186428b0 Ilias Tsitsimpis
    DIMAGES = compute_client.list_images(detail=True)
2138 186428b0 Ilias Tsitsimpis
    DFLAVORS = compute_client.list_flavors(detail=True)
2139 5a140b23 Vangelis Koukis
2140 21bbbc9b Vangelis Koukis
    # FIXME: logging, log, LOG PID, TEST_RUN_ID, arguments
2141 5a140b23 Vangelis Koukis
    # Run them: FIXME: In parallel, FAILEARLY, catchbreak?
2142 5a140b23 Vangelis Koukis
    #unittest.main(verbosity=2, catchbreak=True)
2143 5a140b23 Vangelis Koukis
2144 6e168615 Ilias Tsitsimpis
    # Get a list of images we are going to test
2145 e94a9d8c John Giannelos
    if opts.force_imageid == 'all':
2146 e94a9d8c John Giannelos
        test_images = DIMAGES
2147 e94a9d8c John Giannelos
    else:
2148 e94a9d8c John Giannelos
        test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
2149 e94a9d8c John Giannelos
2150 6e168615 Ilias Tsitsimpis
    # Create output (logging) folder
2151 74ec726f John Giannelos
    if not os.path.exists(opts.log_folder):
2152 74ec726f John Giannelos
        os.mkdir(opts.log_folder)
2153 2bcfb712 John Giannelos
    test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
2154 74ec726f John Giannelos
    os.mkdir(test_folder)
2155 81e8cbf6 John Giannelos
2156 00f87624 Vangelis Koukis
    for image in test_images:
2157 99d41650 John Giannelos
        imageid = str(image["id"])
2158 6e168615 Ilias Tsitsimpis
        imagename = image["name"]
2159 6e168615 Ilias Tsitsimpis
        # Choose a flavor (given from user or random)
2160 81e8cbf6 John Giannelos
        if opts.force_flavorid:
2161 81e8cbf6 John Giannelos
            flavorid = opts.force_flavorid
2162 81e8cbf6 John Giannelos
        else:
2163 81e8cbf6 John Giannelos
            flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
2164 6e168615 Ilias Tsitsimpis
        # Personality dictionary for file injection test
2165 6e168615 Ilias Tsitsimpis
        if opts.personality_path is not None:
2166 9659e075 John Giannelos
            f = open(opts.personality_path)
2167 9659e075 John Giannelos
            content = b64encode(f.read())
2168 9659e075 John Giannelos
            personality = []
2169 9659e075 John Giannelos
            st = os.stat(opts.personality_path)
2170 9659e075 John Giannelos
            personality.append({
2171 6e168615 Ilias Tsitsimpis
                'path': '/root/test_inj_file',
2172 6e168615 Ilias Tsitsimpis
                'owner': 'root',
2173 6e168615 Ilias Tsitsimpis
                'group': 'root',
2174 6e168615 Ilias Tsitsimpis
                'mode': 0x7777 & st.st_mode,
2175 6e168615 Ilias Tsitsimpis
                'contents': content})
2176 9659e075 John Giannelos
        else:
2177 9659e075 John Giannelos
            personality = None
2178 6e168615 Ilias Tsitsimpis
        # Give a name to our test servers
2179 21bbbc9b Vangelis Koukis
        servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
2180 21bbbc9b Vangelis Koukis
        is_windows = imagename.lower().find("windows") >= 0
2181 8252d64f John Giannelos
2182 6e168615 Ilias Tsitsimpis
        # Create Server TestCases
2183 8252d64f John Giannelos
        ServerTestCase = _spawn_server_test_case(
2184 8252d64f John Giannelos
            imageid=imageid,
2185 8252d64f John Giannelos
            flavorid=flavorid,
2186 8252d64f John Giannelos
            imagename=imagename,
2187 8252d64f John Giannelos
            personality=personality,
2188 8252d64f John Giannelos
            servername=servername,
2189 8252d64f John Giannelos
            is_windows=is_windows,
2190 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
2191 8252d64f John Giannelos
            build_warning=opts.build_warning,
2192 8252d64f John Giannelos
            build_fail=opts.build_fail,
2193 6e168615 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2194 6e168615 Ilias Tsitsimpis
        # Create Network TestCases
2195 8252d64f John Giannelos
        NetworkTestCase = _spawn_network_test_case(
2196 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
2197 8252d64f John Giannelos
            imageid=imageid,
2198 8252d64f John Giannelos
            flavorid=flavorid,
2199 8252d64f John Giannelos
            imagename=imagename,
2200 6e168615 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2201 95a87099 Ilias Tsitsimpis
        # Create Images TestCase
2202 95a87099 Ilias Tsitsimpis
        CImagesTestCase = _images_test_case(
2203 95a87099 Ilias Tsitsimpis
            action_timeout=opts.action_timeout,
2204 95a87099 Ilias Tsitsimpis
            imageid=imageid,
2205 95a87099 Ilias Tsitsimpis
            flavorid=flavorid,
2206 95a87099 Ilias Tsitsimpis
            imagename=imagename,
2207 95a87099 Ilias Tsitsimpis
            query_interval=opts.query_interval)
2208 8252d64f John Giannelos
2209 6e168615 Ilias Tsitsimpis
        # Choose the tests we are going to run
2210 746540cd John Giannelos
        test_dict = {'auth': UnauthorizedTestCase,
2211 95a87099 Ilias Tsitsimpis
                     'images': CImagesTestCase,
2212 746540cd John Giannelos
                     'flavors': FlavorsTestCase,
2213 746540cd John Giannelos
                     'servers': ServersTestCase,
2214 11779b6c Ilias Tsitsimpis
                     'pithos': PithosTestCase,
2215 746540cd John Giannelos
                     'server_spawn': ServerTestCase,
2216 746540cd John Giannelos
                     'network_spawn': NetworkTestCase}
2217 22efe1fe John Giannelos
        seq_cases = []
2218 22efe1fe John Giannelos
        if 'all' in opts.tests:
2219 4d72f9ab Ilias Tsitsimpis
            seq_cases = [UnauthorizedTestCase, CImagesTestCase,
2220 11779b6c Ilias Tsitsimpis
                         FlavorsTestCase, ServersTestCase,
2221 11779b6c Ilias Tsitsimpis
                         PithosTestCase, ServerTestCase,
2222 11779b6c Ilias Tsitsimpis
                         NetworkTestCase]
2223 22efe1fe John Giannelos
        else:
2224 22efe1fe John Giannelos
            for test in opts.tests:
2225 22efe1fe John Giannelos
                seq_cases.append(test_dict[test])
2226 22efe1fe John Giannelos
2227 6e168615 Ilias Tsitsimpis
        # Folder for each image
2228 2bcfb712 John Giannelos
        image_folder = os.path.join(test_folder, imageid)
2229 81e8cbf6 John Giannelos
        os.mkdir(image_folder)
2230 81e8cbf6 John Giannelos
2231 6e168615 Ilias Tsitsimpis
        # Run each test
2232 6e168615 Ilias Tsitsimpis
        if opts.fanout > 1:
2233 3e4c5c32 John Giannelos
            _run_cases_in_parallel(seq_cases, opts.fanout, image_folder)
2234 3e4c5c32 John Giannelos
        else:
2235 6e168615 Ilias Tsitsimpis
            _run_cases_in_series(seq_cases, image_folder)
2236 6e168615 Ilias Tsitsimpis
2237 746540cd John Giannelos
2238 6e168615 Ilias Tsitsimpis
# --------------------------------------------------------------------
2239 6e168615 Ilias Tsitsimpis
# Call main
2240 5a140b23 Vangelis Koukis
if __name__ == "__main__":
2241 5a140b23 Vangelis Koukis
    sys.exit(main())