Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin.py @ 4c9918f9

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

745 f752215c John Giannelos
        Implementation of RFB protocol follows
746 f752215c John Giannelos
        http://www.realvnc.com/docs/rfbproto.pdf.
747 bc14ba88 Vangelis Koukis

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

1645 21bbbc9b Vangelis Koukis
    The cases iterable specifies the TestCases to be executed in parallel,
1646 21bbbc9b Vangelis Koukis
    by test runners running in distinct processes.
1647 21bbbc9b Vangelis Koukis
    The fanout parameter specifies the number of processes to spawn,
1648 21bbbc9b Vangelis Koukis
    and defaults to 1.
1649 21bbbc9b Vangelis Koukis
    The runner argument specifies the test runner class to use inside each
1650 21bbbc9b Vangelis Koukis
    runner process.
1651 21bbbc9b Vangelis Koukis

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

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

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