Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin.py @ 2aaa1336

History | View | Annotate | Download (63 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 21bbbc9b Vangelis Koukis
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 5a140b23 Vangelis Koukis
import paramiko
44 21bbbc9b Vangelis Koukis
import prctl
45 5a140b23 Vangelis Koukis
import subprocess
46 21bbbc9b Vangelis Koukis
import signal
47 5a140b23 Vangelis Koukis
import socket
48 5a140b23 Vangelis Koukis
import sys
49 5a140b23 Vangelis Koukis
import time
50 9659e075 John Giannelos
from base64 import b64encode
51 5a140b23 Vangelis Koukis
from IPy import IP
52 21bbbc9b Vangelis Koukis
from multiprocessing import Process, Queue
53 bc14ba88 Vangelis Koukis
from random import choice
54 22efe1fe John Giannelos
from optparse import OptionParser, OptionValueError
55 21bbbc9b Vangelis Koukis
56 96da37c8 John Giannelos
from kamaki.clients.compute import ComputeClient
57 96da37c8 John Giannelos
from kamaki.clients.cyclades import CycladesClient
58 946da8b6 John Giannelos
from kamaki.clients.image import ImageClient
59 21dcb666 John Giannelos
from kamaki.clients import ClientError
60 96da37c8 John Giannelos
61 88736f65 John Giannelos
from fabric.api import *
62 1c636ad6 John Giannelos
63 bc14ba88 Vangelis Koukis
from vncauthproxy.d3des import generate_response as d3des_generate_response
64 5a140b23 Vangelis Koukis
65 5a140b23 Vangelis Koukis
# Use backported unittest functionality if Python < 2.7
66 5a140b23 Vangelis Koukis
try:
67 5a140b23 Vangelis Koukis
    import unittest2 as unittest
68 5a140b23 Vangelis Koukis
except ImportError:
69 bc14ba88 Vangelis Koukis
    if sys.version_info < (2, 7):
70 bc14ba88 Vangelis Koukis
        raise Exception("The unittest2 package is required for Python < 2.7")
71 5a140b23 Vangelis Koukis
    import unittest
72 5a140b23 Vangelis Koukis
73 5a140b23 Vangelis Koukis
74 21bbbc9b Vangelis Koukis
API = None
75 21bbbc9b Vangelis Koukis
TOKEN = None
76 567ffb85 John Giannelos
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
77 946da8b6 John Giannelos
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
78 946da8b6 John Giannelos
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
79 38d247df Kostas Papadimitriou
80 5a140b23 Vangelis Koukis
# A unique id identifying this test run
81 21bbbc9b Vangelis Koukis
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
82 21bbbc9b Vangelis Koukis
                                         "%Y%m%d%H%M%S")
83 21bbbc9b Vangelis Koukis
SNF_TEST_PREFIX = "snf-test-"
84 5a140b23 Vangelis Koukis
85 746540cd John Giannelos
red = '\x1b[31m'
86 746540cd John Giannelos
yellow = '\x1b[33m'
87 746540cd John Giannelos
green = '\x1b[32m'
88 746540cd John Giannelos
normal = '\x1b[0m'
89 746540cd John Giannelos
90 746540cd John Giannelos
class burninFormatter(logging.Formatter):
91 746540cd John Giannelos
92 746540cd John Giannelos
    err_fmt = red + "ERROR: %(msg)s" + normal
93 9b013c3a John Giannelos
    dbg_fmt = green + "* %(msg)s" + normal
94 746540cd John Giannelos
    info_fmt = "%(msg)s"
95 746540cd John Giannelos
96 746540cd John Giannelos
    def __init__(self, fmt="%(levelno)s: %(msg)s"):
97 746540cd John Giannelos
        logging.Formatter.__init__(self, fmt)
98 746540cd John Giannelos
99 746540cd John Giannelos
    def format(self, record):
100 746540cd John Giannelos
101 746540cd John Giannelos
        format_orig = self._fmt
102 746540cd John Giannelos
103 746540cd John Giannelos
        # Replace the original format with one customized by logging level
104 746540cd John Giannelos
        if record.levelno == 10:    # DEBUG
105 746540cd John Giannelos
            self._fmt = burninFormatter.dbg_fmt
106 746540cd John Giannelos
107 746540cd John Giannelos
        elif record.levelno == 20:  # INFO
108 746540cd John Giannelos
            self._fmt = burninFormatter.info_fmt
109 746540cd John Giannelos
110 746540cd John Giannelos
        elif record.levelno == 40:  # ERROR
111 746540cd John Giannelos
            self._fmt = burninFormatter.err_fmt
112 746540cd John Giannelos
113 746540cd John Giannelos
        result = logging.Formatter.format(self, record)
114 746540cd John Giannelos
        self._fmt = format_orig
115 746540cd John Giannelos
116 746540cd John Giannelos
        return result
117 746540cd John Giannelos
118 00f87624 Vangelis Koukis
log = logging.getLogger("burnin")
119 746540cd John Giannelos
log.setLevel(logging.DEBUG)
120 746540cd John Giannelos
handler = logging.StreamHandler()
121 746540cd John Giannelos
handler.setFormatter(burninFormatter())
122 746540cd John Giannelos
log.addHandler(handler)
123 5a140b23 Vangelis Koukis
124 2bcfb712 John Giannelos
125 5a140b23 Vangelis Koukis
class UnauthorizedTestCase(unittest.TestCase):
126 5a140b23 Vangelis Koukis
    def test_unauthorized_access(self):
127 5a140b23 Vangelis Koukis
        """Test access without a valid token fails"""
128 81e8cbf6 John Giannelos
        log.info("Authentication test")
129 81e8cbf6 John Giannelos
130 1c636ad6 John Giannelos
        falseToken = '12345'
131 2bcfb712 John Giannelos
        c = ComputeClient(API, falseToken)
132 1c636ad6 John Giannelos
133 5a140b23 Vangelis Koukis
        with self.assertRaises(ClientError) as cm:
134 5a140b23 Vangelis Koukis
            c.list_servers()
135 21dcb666 John Giannelos
            self.assertEqual(cm.exception.status, 401)
136 5a140b23 Vangelis Koukis
137 5a140b23 Vangelis Koukis
138 5a140b23 Vangelis Koukis
class ImagesTestCase(unittest.TestCase):
139 5a140b23 Vangelis Koukis
    """Test image lists for consistency"""
140 5a140b23 Vangelis Koukis
    @classmethod
141 5a140b23 Vangelis Koukis
    def setUpClass(cls):
142 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of images"""
143 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of images")
144 1c636ad6 John Giannelos
145 846980fe John Giannelos
        cls.client = ComputeClient(API, TOKEN)
146 946da8b6 John Giannelos
        cls.plankton = ImageClient(PLANKTON, TOKEN)
147 946da8b6 John Giannelos
        cls.images = cls.plankton.list_public()
148 946da8b6 John Giannelos
        cls.dimages = cls.plankton.list_public(detail=True)
149 5a140b23 Vangelis Koukis
150 5a140b23 Vangelis Koukis
    def test_001_list_images(self):
151 5a140b23 Vangelis Koukis
        """Test image list actually returns images"""
152 6207533f John Giannelos
        self.assertGreater(len(self.images), 0)
153 74ec726f John Giannelos
154 5a140b23 Vangelis Koukis
    def test_002_list_images_detailed(self):
155 5a140b23 Vangelis Koukis
        """Test detailed image list is the same length as list"""
156 6207533f John Giannelos
        self.assertEqual(len(self.dimages), len(self.images))
157 74ec726f John Giannelos
158 5a140b23 Vangelis Koukis
    def test_003_same_image_names(self):
159 5a140b23 Vangelis Koukis
        """Test detailed and simple image list contain same names"""
160 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.images))
161 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dimages))
162 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
163 5a140b23 Vangelis Koukis
164 5a140b23 Vangelis Koukis
    def test_004_unique_image_names(self):
165 946da8b6 John Giannelos
        """Test system images have unique names"""
166 946da8b6 John Giannelos
        sys_images = filter(lambda x: x['owner'] == PLANKTON_USER,
167 946da8b6 John Giannelos
                            self.dimages)
168 946da8b6 John Giannelos
        names = sorted(map(lambda x: x["name"], sys_images))
169 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
170 5a140b23 Vangelis Koukis
171 5a140b23 Vangelis Koukis
    def test_005_image_metadata(self):
172 5a140b23 Vangelis Koukis
        """Test every image has specific metadata defined"""
173 2e3b7dc8 John Giannelos
        keys = frozenset(["osfamily", "root_partition"])
174 846980fe John Giannelos
        details = self.client.list_images(detail=True)
175 846980fe John Giannelos
        for i in details:
176 5a140b23 Vangelis Koukis
            self.assertTrue(keys.issubset(i["metadata"]["values"].keys()))
177 5a140b23 Vangelis Koukis
178 5a140b23 Vangelis Koukis
179 5a140b23 Vangelis Koukis
class FlavorsTestCase(unittest.TestCase):
180 5a140b23 Vangelis Koukis
    """Test flavor lists for consistency"""
181 5a140b23 Vangelis Koukis
    @classmethod
182 5a140b23 Vangelis Koukis
    def setUpClass(cls):
183 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of flavors"""
184 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of flavors")
185 1c636ad6 John Giannelos
186 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
187 5a140b23 Vangelis Koukis
        cls.flavors = cls.client.list_flavors()
188 5a140b23 Vangelis Koukis
        cls.dflavors = cls.client.list_flavors(detail=True)
189 5a140b23 Vangelis Koukis
190 5a140b23 Vangelis Koukis
    def test_001_list_flavors(self):
191 5a140b23 Vangelis Koukis
        """Test flavor list actually returns flavors"""
192 5a140b23 Vangelis Koukis
        self.assertGreater(len(self.flavors), 0)
193 5a140b23 Vangelis Koukis
194 5a140b23 Vangelis Koukis
    def test_002_list_flavors_detailed(self):
195 5a140b23 Vangelis Koukis
        """Test detailed flavor list is the same length as list"""
196 5a140b23 Vangelis Koukis
        self.assertEquals(len(self.dflavors), len(self.flavors))
197 5a140b23 Vangelis Koukis
198 5a140b23 Vangelis Koukis
    def test_003_same_flavor_names(self):
199 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
200 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
201 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dflavors))
202 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
203 5a140b23 Vangelis Koukis
204 5a140b23 Vangelis Koukis
    def test_004_unique_flavor_names(self):
205 5a140b23 Vangelis Koukis
        """Test flavors have unique names"""
206 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
207 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
208 5a140b23 Vangelis Koukis
209 5a140b23 Vangelis Koukis
    def test_005_well_formed_flavor_names(self):
210 5a140b23 Vangelis Koukis
        """Test flavors have names of the form CxxRyyDzz
211 5a140b23 Vangelis Koukis

212 5a140b23 Vangelis Koukis
        Where xx is vCPU count, yy is RAM in MiB, zz is Disk in GiB
213 5a140b23 Vangelis Koukis

214 5a140b23 Vangelis Koukis
        """
215 5a140b23 Vangelis Koukis
        for f in self.dflavors:
216 5a140b23 Vangelis Koukis
            self.assertEqual("C%dR%dD%d" % (f["cpu"], f["ram"], f["disk"]),
217 5a140b23 Vangelis Koukis
                             f["name"],
218 5a140b23 Vangelis Koukis
                             "Flavor %s does not match its specs." % f["name"])
219 5a140b23 Vangelis Koukis
220 5a140b23 Vangelis Koukis
221 5a140b23 Vangelis Koukis
class ServersTestCase(unittest.TestCase):
222 5a140b23 Vangelis Koukis
    """Test server lists for consistency"""
223 5a140b23 Vangelis Koukis
    @classmethod
224 5a140b23 Vangelis Koukis
    def setUpClass(cls):
225 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of servers"""
226 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of servers")
227 1c636ad6 John Giannelos
228 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
229 5a140b23 Vangelis Koukis
        cls.servers = cls.client.list_servers()
230 5a140b23 Vangelis Koukis
        cls.dservers = cls.client.list_servers(detail=True)
231 5a140b23 Vangelis Koukis
232 74ec726f John Giannelos
    # def test_001_list_servers(self):
233 74ec726f John Giannelos
    #     """Test server list actually returns servers"""
234 74ec726f John Giannelos
    #     self.assertGreater(len(self.servers), 0)
235 5a140b23 Vangelis Koukis
236 5a140b23 Vangelis Koukis
    def test_002_list_servers_detailed(self):
237 5a140b23 Vangelis Koukis
        """Test detailed server list is the same length as list"""
238 5a140b23 Vangelis Koukis
        self.assertEqual(len(self.dservers), len(self.servers))
239 5a140b23 Vangelis Koukis
240 5a140b23 Vangelis Koukis
    def test_003_same_server_names(self):
241 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
242 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.servers))
243 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dservers))
244 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
245 5a140b23 Vangelis Koukis
246 5a140b23 Vangelis Koukis
247 5a140b23 Vangelis Koukis
# This class gets replicated into actual TestCases dynamically
248 5a140b23 Vangelis Koukis
class SpawnServerTestCase(unittest.TestCase):
249 5a140b23 Vangelis Koukis
    """Test scenario for server of the specified image"""
250 5a140b23 Vangelis Koukis
251 5a140b23 Vangelis Koukis
    @classmethod
252 5a140b23 Vangelis Koukis
    def setUpClass(cls):
253 5a140b23 Vangelis Koukis
        """Initialize a kamaki instance"""
254 2e3b7dc8 John Giannelos
        log.info("Spawning server for image `%s'" %cls.imagename)
255 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
256 567ffb85 John Giannelos
        cls.cyclades = CycladesClient(API, TOKEN)
257 5a140b23 Vangelis Koukis
258 5a140b23 Vangelis Koukis
    def _get_ipv4(self, server):
259 bc14ba88 Vangelis Koukis
        """Get the public IPv4 of a server from the detailed server info"""
260 1c636ad6 John Giannelos
261 2aaa1336 John Giannelos
        public_addrs = filter(lambda x: x["network_id"] == "public",
262 2aaa1336 John Giannelos
                              server["attachments"]["values"])
263 2aaa1336 John Giannelos
264 5a140b23 Vangelis Koukis
        self.assertEqual(len(public_addrs), 1)
265 2aaa1336 John Giannelos
266 2aaa1336 John Giannelos
        self.assertTrue(public_addrs[0]['ipv4'] != None)
267 2aaa1336 John Giannelos
268 2aaa1336 John Giannelos
        return public_addrs[0]['ipv4']
269 5a140b23 Vangelis Koukis
270 5a140b23 Vangelis Koukis
    def _get_ipv6(self, server):
271 bc14ba88 Vangelis Koukis
        """Get the public IPv6 of a server from the detailed server info"""
272 2aaa1336 John Giannelos
273 2aaa1336 John Giannelos
        public_addrs = filter(lambda x: x["network_id"] == "public",
274 2aaa1336 John Giannelos
                              server["attachments"]["values"])
275 2aaa1336 John Giannelos
276 5a140b23 Vangelis Koukis
        self.assertEqual(len(public_addrs), 1)
277 2aaa1336 John Giannelos
278 2aaa1336 John Giannelos
        self.assertTrue(public_addrs[0]['ipv6'] != None)
279 2aaa1336 John Giannelos
280 2aaa1336 John Giannelos
        return public_addrs[0]['ipv6']
281 2aaa1336 John Giannelos
282 2aaa1336 John Giannelos
283 5a140b23 Vangelis Koukis
284 bc14ba88 Vangelis Koukis
    def _connect_loginname(self, os):
285 bc14ba88 Vangelis Koukis
        """Return the login name for connections based on the server OS"""
286 1c636ad6 John Giannelos
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
287 21bbbc9b Vangelis Koukis
            return "user"
288 1c636ad6 John Giannelos
        elif os in ("windows", "windows_alpha1"):
289 21bbbc9b Vangelis Koukis
            return "Administrator"
290 bc14ba88 Vangelis Koukis
        else:
291 21bbbc9b Vangelis Koukis
            return "root"
292 bc14ba88 Vangelis Koukis
293 bc14ba88 Vangelis Koukis
    def _verify_server_status(self, current_status, new_status):
294 bc14ba88 Vangelis Koukis
        """Verify a server has switched to a specified status"""
295 bc14ba88 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
296 21bbbc9b Vangelis Koukis
        if server["status"] not in (current_status, new_status):
297 21bbbc9b Vangelis Koukis
            return None  # Do not raise exception, return so the test fails
298 bc14ba88 Vangelis Koukis
        self.assertEquals(server["status"], new_status)
299 bc14ba88 Vangelis Koukis
300 bc14ba88 Vangelis Koukis
    def _get_connected_tcp_socket(self, family, host, port):
301 bc14ba88 Vangelis Koukis
        """Get a connected socket from the specified family to host:port"""
302 bc14ba88 Vangelis Koukis
        sock = None
303 bc14ba88 Vangelis Koukis
        for res in \
304 bc14ba88 Vangelis Koukis
            socket.getaddrinfo(host, port, family, socket.SOCK_STREAM, 0,
305 bc14ba88 Vangelis Koukis
                               socket.AI_PASSIVE):
306 bc14ba88 Vangelis Koukis
            af, socktype, proto, canonname, sa = res
307 bc14ba88 Vangelis Koukis
            try:
308 bc14ba88 Vangelis Koukis
                sock = socket.socket(af, socktype, proto)
309 bc14ba88 Vangelis Koukis
            except socket.error as msg:
310 bc14ba88 Vangelis Koukis
                sock = None
311 bc14ba88 Vangelis Koukis
                continue
312 bc14ba88 Vangelis Koukis
            try:
313 bc14ba88 Vangelis Koukis
                sock.connect(sa)
314 bc14ba88 Vangelis Koukis
            except socket.error as msg:
315 bc14ba88 Vangelis Koukis
                sock.close()
316 bc14ba88 Vangelis Koukis
                sock = None
317 bc14ba88 Vangelis Koukis
                continue
318 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(sock)
319 bc14ba88 Vangelis Koukis
        return sock
320 bc14ba88 Vangelis Koukis
321 bc14ba88 Vangelis Koukis
    def _ping_once(self, ipv6, ip):
322 bc14ba88 Vangelis Koukis
        """Test server responds to a single IPv4 or IPv6 ping"""
323 bc14ba88 Vangelis Koukis
        cmd = "ping%s -c 2 -w 3 %s" % ("6" if ipv6 else "", ip)
324 bc14ba88 Vangelis Koukis
        ping = subprocess.Popen(cmd, shell=True,
325 bc14ba88 Vangelis Koukis
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
326 bc14ba88 Vangelis Koukis
        (stdout, stderr) = ping.communicate()
327 bc14ba88 Vangelis Koukis
        ret = ping.wait()
328 bc14ba88 Vangelis Koukis
        self.assertEquals(ret, 0)
329 5a140b23 Vangelis Koukis
330 bc14ba88 Vangelis Koukis
    def _get_hostname_over_ssh(self, hostip, username, password):
331 bc14ba88 Vangelis Koukis
        ssh = paramiko.SSHClient()
332 bc14ba88 Vangelis Koukis
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
333 bc14ba88 Vangelis Koukis
        try:
334 bc14ba88 Vangelis Koukis
            ssh.connect(hostip, username=username, password=password)
335 bc14ba88 Vangelis Koukis
        except socket.error:
336 bc14ba88 Vangelis Koukis
            raise AssertionError
337 bc14ba88 Vangelis Koukis
        stdin, stdout, stderr = ssh.exec_command("hostname")
338 bc14ba88 Vangelis Koukis
        lines = stdout.readlines()
339 bc14ba88 Vangelis Koukis
        self.assertEqual(len(lines), 1)
340 4fdd25ab Vangelis Koukis
        return lines[0]
341 bc14ba88 Vangelis Koukis
342 bc14ba88 Vangelis Koukis
    def _try_until_timeout_expires(self, warn_timeout, fail_timeout,
343 bc14ba88 Vangelis Koukis
                                   opmsg, callable, *args, **kwargs):
344 bc14ba88 Vangelis Koukis
        if warn_timeout == fail_timeout:
345 5a140b23 Vangelis Koukis
            warn_timeout = fail_timeout + 1
346 5a140b23 Vangelis Koukis
        warn_tmout = time.time() + warn_timeout
347 5a140b23 Vangelis Koukis
        fail_tmout = time.time() + fail_timeout
348 5a140b23 Vangelis Koukis
        while True:
349 4fdd25ab Vangelis Koukis
            self.assertLess(time.time(), fail_tmout,
350 21bbbc9b Vangelis Koukis
                            "operation `%s' timed out" % opmsg)
351 5a140b23 Vangelis Koukis
            if time.time() > warn_tmout:
352 4fdd25ab Vangelis Koukis
                log.warning("Server %d: `%s' operation `%s' not done yet",
353 4fdd25ab Vangelis Koukis
                            self.serverid, self.servername, opmsg)
354 bc14ba88 Vangelis Koukis
            try:
355 4fdd25ab Vangelis Koukis
                log.info("%s... " % opmsg)
356 bc14ba88 Vangelis Koukis
                return callable(*args, **kwargs)
357 bc14ba88 Vangelis Koukis
            except AssertionError:
358 bc14ba88 Vangelis Koukis
                pass
359 5a140b23 Vangelis Koukis
            time.sleep(self.query_interval)
360 5a140b23 Vangelis Koukis
361 bc14ba88 Vangelis Koukis
    def _insist_on_tcp_connection(self, family, host, port):
362 21bbbc9b Vangelis Koukis
        familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6",
363 21bbbc9b Vangelis Koukis
                     socket.AF_UNSPEC: "Unspecified-IPv4/6"}
364 bc14ba88 Vangelis Koukis
        msg = "connect over %s to %s:%s" % \
365 bc14ba88 Vangelis Koukis
              (familystr.get(family, "Unknown"), host, port)
366 bc14ba88 Vangelis Koukis
        sock = self._try_until_timeout_expires(
367 bc14ba88 Vangelis Koukis
                self.action_timeout, self.action_timeout,
368 bc14ba88 Vangelis Koukis
                msg, self._get_connected_tcp_socket,
369 bc14ba88 Vangelis Koukis
                family, host, port)
370 bc14ba88 Vangelis Koukis
        return sock
371 bc14ba88 Vangelis Koukis
372 bc14ba88 Vangelis Koukis
    def _insist_on_status_transition(self, current_status, new_status,
373 bc14ba88 Vangelis Koukis
                                    fail_timeout, warn_timeout=None):
374 4fdd25ab Vangelis Koukis
        msg = "Server %d: `%s', waiting for %s -> %s" % \
375 4fdd25ab Vangelis Koukis
              (self.serverid, self.servername, current_status, new_status)
376 bc14ba88 Vangelis Koukis
        if warn_timeout is None:
377 bc14ba88 Vangelis Koukis
            warn_timeout = fail_timeout
378 bc14ba88 Vangelis Koukis
        self._try_until_timeout_expires(warn_timeout, fail_timeout,
379 bc14ba88 Vangelis Koukis
                                        msg, self._verify_server_status,
380 bc14ba88 Vangelis Koukis
                                        current_status, new_status)
381 21bbbc9b Vangelis Koukis
        # Ensure the status is actually the expected one
382 21bbbc9b Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
383 21bbbc9b Vangelis Koukis
        self.assertEquals(server["status"], new_status)
384 bc14ba88 Vangelis Koukis
385 bc14ba88 Vangelis Koukis
    def _insist_on_ssh_hostname(self, hostip, username, password):
386 4fdd25ab Vangelis Koukis
        msg = "SSH to %s, as %s/%s" % (hostip, username, password)
387 bc14ba88 Vangelis Koukis
        hostname = self._try_until_timeout_expires(
388 bc14ba88 Vangelis Koukis
                self.action_timeout, self.action_timeout,
389 bc14ba88 Vangelis Koukis
                msg, self._get_hostname_over_ssh,
390 bc14ba88 Vangelis Koukis
                hostip, username, password)
391 bc14ba88 Vangelis Koukis
392 bc14ba88 Vangelis Koukis
        # The hostname must be of the form 'prefix-id'
393 bc14ba88 Vangelis Koukis
        self.assertTrue(hostname.endswith("-%d\n" % self.serverid))
394 5a140b23 Vangelis Koukis
395 8252d64f John Giannelos
    def _check_file_through_ssh(self, hostip, username, password,
396 8252d64f John Giannelos
                                remotepath, content):
397 8252d64f John Giannelos
        msg = "Trying file injection through SSH to %s, as %s/%s" % \
398 8252d64f John Giannelos
            (hostip, username, password)
399 f97dce4d John Giannelos
        log.info(msg)
400 77054bf5 John Giannelos
        try:
401 77054bf5 John Giannelos
            ssh = paramiko.SSHClient()
402 77054bf5 John Giannelos
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
403 77054bf5 John Giannelos
            ssh.connect(hostip, username=username, password=password)
404 77054bf5 John Giannelos
        except socket.error:
405 77054bf5 John Giannelos
            raise AssertionError
406 9659e075 John Giannelos
407 2bcfb712 John Giannelos
        transport = paramiko.Transport((hostip, 22))
408 2bcfb712 John Giannelos
        transport.connect(username=username, password=password)
409 2bcfb712 John Giannelos
410 2bcfb712 John Giannelos
        localpath = '/tmp/' + SNF_TEST_PREFIX + 'injection'
411 77054bf5 John Giannelos
        sftp = paramiko.SFTPClient.from_transport(transport)
412 8252d64f John Giannelos
        sftp.get(remotepath, localpath)
413 77054bf5 John Giannelos
        sftp.close()
414 77054bf5 John Giannelos
        transport.close()
415 77054bf5 John Giannelos
416 9659e075 John Giannelos
        f = open(localpath)
417 9659e075 John Giannelos
        remote_content = b64encode(f.read())
418 9659e075 John Giannelos
419 77054bf5 John Giannelos
        # Check if files are the same
420 65462ca9 John Giannelos
        return (remote_content == content)
421 77054bf5 John Giannelos
422 5a140b23 Vangelis Koukis
    def _skipIf(self, condition, msg):
423 5a140b23 Vangelis Koukis
        if condition:
424 5a140b23 Vangelis Koukis
            self.skipTest(msg)
425 5a140b23 Vangelis Koukis
426 5a140b23 Vangelis Koukis
    def test_001_submit_create_server(self):
427 5a140b23 Vangelis Koukis
        """Test submit create server request"""
428 f89d0238 John Giannelos
429 f89d0238 John Giannelos
        log.info("Submit new server request")
430 5a140b23 Vangelis Koukis
        server = self.client.create_server(self.servername, self.flavorid,
431 5a140b23 Vangelis Koukis
                                           self.imageid, self.personality)
432 9659e075 John Giannelos
433 81e8cbf6 John Giannelos
        log.info("Server id: " + str(server["id"]))
434 81e8cbf6 John Giannelos
        log.info("Server password: " + server["adminPass"])
435 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
436 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
437 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
438 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
439 5a140b23 Vangelis Koukis
440 5a140b23 Vangelis Koukis
        # Update class attributes to reflect data on building server
441 5a140b23 Vangelis Koukis
        cls = type(self)
442 5a140b23 Vangelis Koukis
        cls.serverid = server["id"]
443 bc14ba88 Vangelis Koukis
        cls.username = None
444 5a140b23 Vangelis Koukis
        cls.passwd = server["adminPass"]
445 5a140b23 Vangelis Koukis
446 5a140b23 Vangelis Koukis
    def test_002a_server_is_building_in_list(self):
447 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in server list"""
448 f89d0238 John Giannelos
        log.info("Server in BUILD state in server list")
449 f89d0238 John Giannelos
450 5a140b23 Vangelis Koukis
        servers = self.client.list_servers(detail=True)
451 5a140b23 Vangelis Koukis
        servers = filter(lambda x: x["name"] == self.servername, servers)
452 2aaa1336 John Giannelos
453 5a140b23 Vangelis Koukis
        server = servers[0]
454 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
455 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
456 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
457 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
458 5a140b23 Vangelis Koukis
459 5a140b23 Vangelis Koukis
    def test_002b_server_is_building_in_details(self):
460 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in details"""
461 f89d0238 John Giannelos
462 f89d0238 John Giannelos
        log.info("Server in BUILD state in details")
463 f89d0238 John Giannelos
464 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
465 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
466 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
467 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
468 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
469 5a140b23 Vangelis Koukis
470 5a140b23 Vangelis Koukis
    def test_002c_set_server_metadata(self):
471 f89d0238 John Giannelos
472 f89d0238 John Giannelos
        log.info("Creating server metadata")
473 f89d0238 John Giannelos
474 5a140b23 Vangelis Koukis
        image = self.client.get_image_details(self.imageid)
475 74193008 John Giannelos
        os = image["metadata"]["values"]["os"]
476 e49bdb7c John Giannelos
        users = image["metadata"]["values"].get("users", None)
477 c1d11f96 John Giannelos
        self.client.update_server_metadata(self.serverid, OS=os)
478 746540cd John Giannelos
479 e49bdb7c John Giannelos
        userlist = users.split()
480 81e8cbf6 John Giannelos
481 bc14ba88 Vangelis Koukis
        # Determine the username to use for future connections
482 bc14ba88 Vangelis Koukis
        # to this host
483 bc14ba88 Vangelis Koukis
        cls = type(self)
484 81e8cbf6 John Giannelos
485 81e8cbf6 John Giannelos
        if "root" in userlist:
486 81e8cbf6 John Giannelos
            cls.username = "root"
487 81e8cbf6 John Giannelos
        elif users == None:
488 bc14ba88 Vangelis Koukis
            cls.username = self._connect_loginname(os)
489 81e8cbf6 John Giannelos
        else:
490 81e8cbf6 John Giannelos
            cls.username = choice(userlist)
491 81e8cbf6 John Giannelos
492 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(cls.username)
493 5a140b23 Vangelis Koukis
494 5a140b23 Vangelis Koukis
    def test_002d_verify_server_metadata(self):
495 5a140b23 Vangelis Koukis
        """Test server metadata keys are set based on image metadata"""
496 f89d0238 John Giannelos
497 f89d0238 John Giannelos
        log.info("Verifying image metadata")
498 f89d0238 John Giannelos
499 5a140b23 Vangelis Koukis
        servermeta = self.client.get_server_metadata(self.serverid)
500 5a140b23 Vangelis Koukis
        imagemeta = self.client.get_image_metadata(self.imageid)
501 81e8cbf6 John Giannelos
502 99d41650 John Giannelos
        self.assertEqual(servermeta["OS"], imagemeta["os"])
503 5a140b23 Vangelis Koukis
504 5a140b23 Vangelis Koukis
    def test_003_server_becomes_active(self):
505 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE"""
506 f89d0238 John Giannelos
507 f89d0238 John Giannelos
        log.info("Waiting for server to become ACTIVE")
508 f89d0238 John Giannelos
509 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("BUILD", "ACTIVE",
510 5a140b23 Vangelis Koukis
                                         self.build_fail, self.build_warning)
511 5a140b23 Vangelis Koukis
512 2aaa1336 John Giannelos
    # def test_003a_get_server_oob_console(self):
513 2aaa1336 John Giannelos
    #     """Test getting OOB server console over VNC
514 bc14ba88 Vangelis Koukis
515 2aaa1336 John Giannelos
    #     Implementation of RFB protocol follows
516 2aaa1336 John Giannelos
    #     http://www.realvnc.com/docs/rfbproto.pdf.
517 bc14ba88 Vangelis Koukis
518 2aaa1336 John Giannelos
    #     """
519 2aaa1336 John Giannelos
    #     console = self.cyclades.get_server_console(self.serverid)
520 2aaa1336 John Giannelos
    #     self.assertEquals(console['type'], "vnc")
521 2aaa1336 John Giannelos
    #     sock = self._insist_on_tcp_connection(socket.AF_INET,
522 2aaa1336 John Giannelos
    #                                     console["host"], console["port"])
523 2aaa1336 John Giannelos
524 2aaa1336 John Giannelos
    #     # Step 1. ProtocolVersion message (par. 6.1.1)
525 2aaa1336 John Giannelos
    #     version = sock.recv(1024)
526 2aaa1336 John Giannelos
    #     self.assertEquals(version, 'RFB 003.008\n')
527 2aaa1336 John Giannelos
    #     sock.send(version)
528 2aaa1336 John Giannelos
529 2aaa1336 John Giannelos
    #     # Step 2. Security (par 6.1.2): Only VNC Authentication supported
530 2aaa1336 John Giannelos
    #     sec = sock.recv(1024)
531 2aaa1336 John Giannelos
    #     self.assertEquals(list(sec), ['\x01', '\x02'])
532 2aaa1336 John Giannelos
533 2aaa1336 John Giannelos
    #     # Step 3. Request VNC Authentication (par 6.1.2)
534 2aaa1336 John Giannelos
    #     sock.send('\x02')
535 2aaa1336 John Giannelos
536 2aaa1336 John Giannelos
    #     # Step 4. Receive Challenge (par 6.2.2)
537 2aaa1336 John Giannelos
    #     challenge = sock.recv(1024)
538 2aaa1336 John Giannelos
    #     self.assertEquals(len(challenge), 16)
539 2aaa1336 John Giannelos
540 2aaa1336 John Giannelos
    #     # Step 5. DES-Encrypt challenge, use password as key (par 6.2.2)
541 2aaa1336 John Giannelos
    #     response = d3des_generate_response(
542 2aaa1336 John Giannelos
    #         (console["password"] + '\0' * 8)[:8], challenge)
543 2aaa1336 John Giannelos
    #     sock.send(response)
544 2aaa1336 John Giannelos
545 2aaa1336 John Giannelos
    #     # Step 6. SecurityResult (par 6.1.3)
546 2aaa1336 John Giannelos
    #     result = sock.recv(4)
547 2aaa1336 John Giannelos
    #     self.assertEquals(list(result), ['\x00', '\x00', '\x00', '\x00'])
548 2aaa1336 John Giannelos
    #     sock.close()
549 8252d64f John Giannelos
550 5a140b23 Vangelis Koukis
    def test_004_server_has_ipv4(self):
551 5a140b23 Vangelis Koukis
        """Test active server has a valid IPv4 address"""
552 f89d0238 John Giannelos
553 81e8cbf6 John Giannelos
        log.info("Validate server's IPv4")
554 f89d0238 John Giannelos
555 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
556 5a140b23 Vangelis Koukis
        ipv4 = self._get_ipv4(server)
557 5a140b23 Vangelis Koukis
        self.assertEquals(IP(ipv4).version(), 4)
558 5a140b23 Vangelis Koukis
559 65462ca9 John Giannelos
    def test_005_server_has_ipv6(self):
560 65462ca9 John Giannelos
        """Test active server has a valid IPv6 address"""
561 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
562 f89d0238 John Giannelos
563 81e8cbf6 John Giannelos
        log.info("Validate server's IPv6")
564 f89d0238 John Giannelos
565 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
566 65462ca9 John Giannelos
        ipv6 = self._get_ipv6(server)
567 65462ca9 John Giannelos
        self.assertEquals(IP(ipv6).version(), 6)
568 5a140b23 Vangelis Koukis
569 5a140b23 Vangelis Koukis
    def test_006_server_responds_to_ping_IPv4(self):
570 5a140b23 Vangelis Koukis
        """Test server responds to ping on IPv4 address"""
571 f89d0238 John Giannelos
572 f89d0238 John Giannelos
        log.info("Testing if server responds to pings in IPv4")
573 f89d0238 John Giannelos
574 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
575 bc14ba88 Vangelis Koukis
        ip = self._get_ipv4(server)
576 bc14ba88 Vangelis Koukis
        self._try_until_timeout_expires(self.action_timeout,
577 bc14ba88 Vangelis Koukis
                                        self.action_timeout,
578 4fdd25ab Vangelis Koukis
                                        "PING IPv4 to %s" % ip,
579 4fdd25ab Vangelis Koukis
                                        self._ping_once,
580 bc14ba88 Vangelis Koukis
                                        False, ip)
581 5a140b23 Vangelis Koukis
582 65462ca9 John Giannelos
    def test_007_server_responds_to_ping_IPv6(self):
583 65462ca9 John Giannelos
        """Test server responds to ping on IPv6 address"""
584 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
585 f89d0238 John Giannelos
        log.info("Testing if server responds to pings in IPv6")
586 f89d0238 John Giannelos
587 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
588 65462ca9 John Giannelos
        ip = self._get_ipv6(server)
589 65462ca9 John Giannelos
        self._try_until_timeout_expires(self.action_timeout,
590 65462ca9 John Giannelos
                                        self.action_timeout,
591 65462ca9 John Giannelos
                                        "PING IPv6 to %s" % ip,
592 65462ca9 John Giannelos
                                        self._ping_once,
593 65462ca9 John Giannelos
                                        True, ip)
594 5a140b23 Vangelis Koukis
595 5a140b23 Vangelis Koukis
    def test_008_submit_shutdown_request(self):
596 5a140b23 Vangelis Koukis
        """Test submit request to shutdown server"""
597 f89d0238 John Giannelos
598 f89d0238 John Giannelos
        log.info("Shutting down server")
599 f89d0238 John Giannelos
600 74193008 John Giannelos
        self.cyclades.shutdown_server(self.serverid)
601 5a140b23 Vangelis Koukis
602 5a140b23 Vangelis Koukis
    def test_009_server_becomes_stopped(self):
603 5a140b23 Vangelis Koukis
        """Test server becomes STOPPED"""
604 f89d0238 John Giannelos
605 f89d0238 John Giannelos
        log.info("Waiting until server becomes STOPPED")
606 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("ACTIVE", "STOPPED",
607 bc14ba88 Vangelis Koukis
                                         self.action_timeout,
608 5a140b23 Vangelis Koukis
                                         self.action_timeout)
609 5a140b23 Vangelis Koukis
610 5a140b23 Vangelis Koukis
    def test_010_submit_start_request(self):
611 5a140b23 Vangelis Koukis
        """Test submit start server request"""
612 f89d0238 John Giannelos
613 f89d0238 John Giannelos
        log.info("Starting server")
614 f89d0238 John Giannelos
615 74193008 John Giannelos
        self.cyclades.start_server(self.serverid)
616 5a140b23 Vangelis Koukis
617 5a140b23 Vangelis Koukis
    def test_011_server_becomes_active(self):
618 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE again"""
619 f89d0238 John Giannelos
620 f89d0238 John Giannelos
        log.info("Waiting until server becomes ACTIVE")
621 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("STOPPED", "ACTIVE",
622 bc14ba88 Vangelis Koukis
                                         self.action_timeout,
623 5a140b23 Vangelis Koukis
                                         self.action_timeout)
624 5a140b23 Vangelis Koukis
625 5a140b23 Vangelis Koukis
    def test_011a_server_responds_to_ping_IPv4(self):
626 5a140b23 Vangelis Koukis
        """Test server OS is actually up and running again"""
627 f89d0238 John Giannelos
628 f89d0238 John Giannelos
        log.info("Testing if server is actually up and running")
629 f89d0238 John Giannelos
630 5a140b23 Vangelis Koukis
        self.test_006_server_responds_to_ping_IPv4()
631 5a140b23 Vangelis Koukis
632 5a140b23 Vangelis Koukis
    def test_012_ssh_to_server_IPv4(self):
633 5a140b23 Vangelis Koukis
        """Test SSH to server public IPv4 works, verify hostname"""
634 f89d0238 John Giannelos
635 bc14ba88 Vangelis Koukis
        self._skipIf(self.is_windows, "only valid for Linux servers")
636 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
637 bc14ba88 Vangelis Koukis
        self._insist_on_ssh_hostname(self._get_ipv4(server),
638 bc14ba88 Vangelis Koukis
                                     self.username, self.passwd)
639 5a140b23 Vangelis Koukis
640 65462ca9 John Giannelos
    def test_013_ssh_to_server_IPv6(self):
641 65462ca9 John Giannelos
        """Test SSH to server public IPv6 works, verify hostname"""
642 65462ca9 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
643 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
644 946da8b6 John Giannelos
645 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
646 65462ca9 John Giannelos
        self._insist_on_ssh_hostname(self._get_ipv6(server),
647 65462ca9 John Giannelos
                                     self.username, self.passwd)
648 5a140b23 Vangelis Koukis
649 5a140b23 Vangelis Koukis
    def test_014_rdp_to_server_IPv4(self):
650 5a140b23 Vangelis Koukis
        "Test RDP connection to server public IPv4 works"""
651 bc14ba88 Vangelis Koukis
        self._skipIf(not self.is_windows, "only valid for Windows servers")
652 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
653 5a140b23 Vangelis Koukis
        ipv4 = self._get_ipv4(server)
654 bc14ba88 Vangelis Koukis
        sock = _insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
655 5a140b23 Vangelis Koukis
656 5a140b23 Vangelis Koukis
        # No actual RDP processing done. We assume the RDP server is there
657 5a140b23 Vangelis Koukis
        # if the connection to the RDP port is successful.
658 cb1fa17c Vangelis Koukis
        # FIXME: Use rdesktop, analyze exit code? see manpage [costasd]
659 5a140b23 Vangelis Koukis
        sock.close()
660 5a140b23 Vangelis Koukis
661 65462ca9 John Giannelos
    def test_015_rdp_to_server_IPv6(self):
662 65462ca9 John Giannelos
        "Test RDP connection to server public IPv6 works"""
663 65462ca9 John Giannelos
        self._skipIf(not self.is_windows, "only valid for Windows servers")
664 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
665 946da8b6 John Giannelos
666 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
667 65462ca9 John Giannelos
        ipv6 = self._get_ipv6(server)
668 65462ca9 John Giannelos
        sock = _get_tcp_connection(socket.AF_INET6, ipv6, 3389)
669 5a140b23 Vangelis Koukis
670 65462ca9 John Giannelos
        # No actual RDP processing done. We assume the RDP server is there
671 65462ca9 John Giannelos
        # if the connection to the RDP port is successful.
672 65462ca9 John Giannelos
        sock.close()
673 5a140b23 Vangelis Koukis
674 5a140b23 Vangelis Koukis
    def test_016_personality_is_enforced(self):
675 5a140b23 Vangelis Koukis
        """Test file injection for personality enforcement"""
676 21dcb666 John Giannelos
        self._skipIf(self.is_windows, "only implemented for Linux servers")
677 21dcb666 John Giannelos
        self._skipIf(self.personality == None, "No personality file selected")
678 f89d0238 John Giannelos
679 f89d0238 John Giannelos
        log.info("Trying to inject file for personality enforcement")
680 f89d0238 John Giannelos
681 77054bf5 John Giannelos
        server = self.client.get_server_details(self.serverid)
682 77054bf5 John Giannelos
683 9659e075 John Giannelos
        for inj_file in self.personality:
684 8252d64f John Giannelos
            equal_files = self._check_file_through_ssh(self._get_ipv4(server),
685 8252d64f John Giannelos
                                                       inj_file['owner'],
686 8252d64f John Giannelos
                                                       self.passwd,
687 8252d64f John Giannelos
                                                       inj_file['path'],
688 8252d64f John Giannelos
                                                       inj_file['contents'])
689 9659e075 John Giannelos
            self.assertTrue(equal_files)
690 8252d64f John Giannelos
691 4fdd25ab Vangelis Koukis
    def test_017_submit_delete_request(self):
692 4fdd25ab Vangelis Koukis
        """Test submit request to delete server"""
693 f89d0238 John Giannelos
694 f89d0238 John Giannelos
        log.info("Deleting server")
695 f89d0238 John Giannelos
696 4fdd25ab Vangelis Koukis
        self.client.delete_server(self.serverid)
697 4fdd25ab Vangelis Koukis
698 4fdd25ab Vangelis Koukis
    def test_018_server_becomes_deleted(self):
699 4fdd25ab Vangelis Koukis
        """Test server becomes DELETED"""
700 f89d0238 John Giannelos
701 f89d0238 John Giannelos
        log.info("Testing if server becomes DELETED")
702 f89d0238 John Giannelos
703 4fdd25ab Vangelis Koukis
        self._insist_on_status_transition("ACTIVE", "DELETED",
704 4fdd25ab Vangelis Koukis
                                         self.action_timeout,
705 4fdd25ab Vangelis Koukis
                                         self.action_timeout)
706 4fdd25ab Vangelis Koukis
707 4fdd25ab Vangelis Koukis
    def test_019_server_no_longer_in_server_list(self):
708 4fdd25ab Vangelis Koukis
        """Test server is no longer in server list"""
709 f89d0238 John Giannelos
710 f89d0238 John Giannelos
        log.info("Test if server is no longer listed")
711 f89d0238 John Giannelos
712 4fdd25ab Vangelis Koukis
        servers = self.client.list_servers()
713 21bbbc9b Vangelis Koukis
        self.assertNotIn(self.serverid, [s["id"] for s in servers])
714 21bbbc9b Vangelis Koukis
715 21bbbc9b Vangelis Koukis
716 9e4682b5 John Giannelos
class NetworkTestCase(unittest.TestCase):
717 e94a9d8c John Giannelos
    """ Testing networking in cyclades """
718 8252d64f John Giannelos
719 9e4682b5 John Giannelos
    @classmethod
720 e94a9d8c John Giannelos
    def setUpClass(cls):
721 e94a9d8c John Giannelos
        "Initialize kamaki, get list of current networks"
722 567ffb85 John Giannelos
723 567ffb85 John Giannelos
        cls.client = CycladesClient(API, TOKEN)
724 567ffb85 John Giannelos
        cls.compute = ComputeClient(API, TOKEN)
725 9e4682b5 John Giannelos
726 8252d64f John Giannelos
        cls.servername = "%s%s for %s" % (SNF_TEST_PREFIX,
727 8252d64f John Giannelos
                                          TEST_RUN_ID,
728 8252d64f John Giannelos
                                          cls.imagename)
729 91de9b55 John Giannelos
730 91de9b55 John Giannelos
        #Dictionary initialization for the vms credentials
731 91de9b55 John Giannelos
        cls.serverid = dict()
732 91de9b55 John Giannelos
        cls.username = dict()
733 91de9b55 John Giannelos
        cls.password = dict()
734 846980fe John Giannelos
        cls.is_windows = cls.imagename.lower().find("windows") >= 0
735 e49bdb7c John Giannelos
736 e49bdb7c John Giannelos
    def _skipIf(self, condition, msg):
737 e49bdb7c John Giannelos
        if condition:
738 e49bdb7c John Giannelos
            self.skipTest(msg)
739 91de9b55 John Giannelos
740 1b40b5e3 John Giannelos
    def _get_ipv4(self, server):
741 1b40b5e3 John Giannelos
        """Get the public IPv4 of a server from the detailed server info"""
742 1b40b5e3 John Giannelos
743 2aaa1336 John Giannelos
        public_addrs = filter(lambda x: x["network_id"] == "public",
744 2aaa1336 John Giannelos
                              server["attachments"]["values"])
745 2aaa1336 John Giannelos
746 1b40b5e3 John Giannelos
        self.assertEqual(len(public_addrs), 1)
747 2aaa1336 John Giannelos
748 2aaa1336 John Giannelos
        self.assertTrue(public_addrs[0]['ipv4'] != None)
749 2aaa1336 John Giannelos
750 2aaa1336 John Giannelos
        return public_addrs[0]['ipv4']
751 8252d64f John Giannelos
752 1b40b5e3 John Giannelos
    def _connect_loginname(self, os):
753 1b40b5e3 John Giannelos
        """Return the login name for connections based on the server OS"""
754 1b40b5e3 John Giannelos
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
755 1b40b5e3 John Giannelos
            return "user"
756 1b40b5e3 John Giannelos
        elif os in ("windows", "windows_alpha1"):
757 1b40b5e3 John Giannelos
            return "Administrator"
758 1b40b5e3 John Giannelos
        else:
759 1b40b5e3 John Giannelos
            return "root"
760 1b40b5e3 John Giannelos
761 88736f65 John Giannelos
    def _ping_once(self, ip):
762 8252d64f John Giannelos
763 88736f65 John Giannelos
        """Test server responds to a single IPv4 or IPv6 ping"""
764 88736f65 John Giannelos
        cmd = "ping -c 2 -w 3 %s" % (ip)
765 88736f65 John Giannelos
        ping = subprocess.Popen(cmd, shell=True,
766 88736f65 John Giannelos
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
767 88736f65 John Giannelos
        (stdout, stderr) = ping.communicate()
768 88736f65 John Giannelos
        ret = ping.wait()
769 8252d64f John Giannelos
770 88736f65 John Giannelos
        return (ret == 0)
771 88736f65 John Giannelos
772 740a5649 John Giannelos
    def test_00001a_submit_create_server_A(self):
773 91de9b55 John Giannelos
        """Test submit create server request"""
774 f89d0238 John Giannelos
775 f89d0238 John Giannelos
        log.info("Creating test server A")
776 f89d0238 John Giannelos
777 91de9b55 John Giannelos
        serverA = self.client.create_server(self.servername, self.flavorid,
778 ae139e8a John Giannelos
                                            self.imageid, personality=None)
779 91de9b55 John Giannelos
780 c54e3d4c John Giannelos
        self.assertEqual(serverA["name"], self.servername)
781 c54e3d4c John Giannelos
        self.assertEqual(serverA["flavorRef"], self.flavorid)
782 c54e3d4c John Giannelos
        self.assertEqual(serverA["imageRef"], self.imageid)
783 c54e3d4c John Giannelos
        self.assertEqual(serverA["status"], "BUILD")
784 91de9b55 John Giannelos
785 91de9b55 John Giannelos
        # Update class attributes to reflect data on building server
786 08748d73 John Giannelos
        self.serverid['A'] = serverA["id"]
787 08748d73 John Giannelos
        self.username['A'] = None
788 08748d73 John Giannelos
        self.password['A'] = serverA["adminPass"]
789 91de9b55 John Giannelos
790 81e8cbf6 John Giannelos
        log.info("Server A id:" + str(serverA["id"]))
791 81e8cbf6 John Giannelos
        log.info("Server password " + (self.password['A']))
792 8252d64f John Giannelos
793 740a5649 John Giannelos
    def test_00001b_serverA_becomes_active(self):
794 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
795 8252d64f John Giannelos
796 f89d0238 John Giannelos
        log.info("Waiting until test server A becomes ACTIVE")
797 91de9b55 John Giannelos
798 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
799 91de9b55 John Giannelos
        while True:
800 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
801 91de9b55 John Giannelos
            status = d['status']
802 91de9b55 John Giannelos
            if status == 'ACTIVE':
803 91de9b55 John Giannelos
                active = True
804 91de9b55 John Giannelos
                break
805 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
806 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
807 91de9b55 John Giannelos
            else:
808 91de9b55 John Giannelos
                time.sleep(self.query_interval)
809 91de9b55 John Giannelos
810 91de9b55 John Giannelos
        self.assertTrue(active)
811 91de9b55 John Giannelos
812 740a5649 John Giannelos
    def test_00002a_submit_create_server_B(self):
813 fade8dab John Giannelos
        """Test submit create server request"""
814 8252d64f John Giannelos
815 f89d0238 John Giannelos
        log.info("Creating test server B")
816 f89d0238 John Giannelos
817 fade8dab John Giannelos
        serverB = self.client.create_server(self.servername, self.flavorid,
818 ae139e8a John Giannelos
                                            self.imageid, personality=None)
819 ae139e8a John Giannelos
820 fade8dab John Giannelos
        self.assertEqual(serverB["name"], self.servername)
821 fade8dab John Giannelos
        self.assertEqual(serverB["flavorRef"], self.flavorid)
822 fade8dab John Giannelos
        self.assertEqual(serverB["imageRef"], self.imageid)
823 fade8dab John Giannelos
        self.assertEqual(serverB["status"], "BUILD")
824 fade8dab John Giannelos
825 fade8dab John Giannelos
        # Update class attributes to reflect data on building server
826 fade8dab John Giannelos
        self.serverid['B'] = serverB["id"]
827 fade8dab John Giannelos
        self.username['B'] = None
828 fade8dab John Giannelos
        self.password['B'] = serverB["adminPass"]
829 fade8dab John Giannelos
830 81e8cbf6 John Giannelos
        log.info("Server B id: " + str(serverB["id"]))
831 81e8cbf6 John Giannelos
        log.info("Password " + (self.password['B']))
832 ae139e8a John Giannelos
833 740a5649 John Giannelos
    def test_00002b_serverB_becomes_active(self):
834 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
835 91de9b55 John Giannelos
836 f89d0238 John Giannelos
        log.info("Waiting until test server B becomes ACTIVE")
837 f89d0238 John Giannelos
838 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
839 91de9b55 John Giannelos
        while True:
840 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
841 91de9b55 John Giannelos
            status = d['status']
842 91de9b55 John Giannelos
            if status == 'ACTIVE':
843 91de9b55 John Giannelos
                active = True
844 91de9b55 John Giannelos
                break
845 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
846 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
847 91de9b55 John Giannelos
            else:
848 91de9b55 John Giannelos
                time.sleep(self.query_interval)
849 91de9b55 John Giannelos
850 91de9b55 John Giannelos
        self.assertTrue(active)
851 567ffb85 John Giannelos
852 9e4682b5 John Giannelos
    def test_001_create_network(self):
853 e94a9d8c John Giannelos
        """Test submit create network request"""
854 f89d0238 John Giannelos
855 f89d0238 John Giannelos
        log.info("Submit new network request")
856 f89d0238 John Giannelos
857 2bcfb712 John Giannelos
        name = SNF_TEST_PREFIX + TEST_RUN_ID
858 9e4682b5 John Giannelos
        previous_num = len(self.client.list_networks())
859 2aaa1336 John Giannelos
        network = self.client.create_network(name,cidr='10.0.0.1/28')
860 8252d64f John Giannelos
861 9e4682b5 John Giannelos
        #Test if right name is assigned
862 e94a9d8c John Giannelos
        self.assertEqual(network['name'], name)
863 8252d64f John Giannelos
864 9e4682b5 John Giannelos
        # Update class attributes
865 e94a9d8c John Giannelos
        cls = type(self)
866 e94a9d8c John Giannelos
        cls.networkid = network['id']
867 9e4682b5 John Giannelos
        networks = self.client.list_networks()
868 9e4682b5 John Giannelos
869 2aaa1336 John Giannelos
        fail_tmout = time.time() + self.action_timeout
870 2aaa1336 John Giannelos
871 9e4682b5 John Giannelos
        #Test if new network is created
872 2aaa1336 John Giannelos
        while True:
873 2aaa1336 John Giannelos
            d = self.client.get_network_details(network['id'])
874 2aaa1336 John Giannelos
            if d['status'] == 'ACTIVE':
875 2aaa1336 John Giannelos
                connected = True
876 2aaa1336 John Giannelos
                break
877 2aaa1336 John Giannelos
            elif time.time() > fail_tmout:
878 2aaa1336 John Giannelos
                self.assertLess(time.time(), fail_tmout)
879 2aaa1336 John Giannelos
            else:
880 2aaa1336 John Giannelos
                log.info("Waiting for network to become ACTIVE")
881 2aaa1336 John Giannelos
                time.sleep(self.query_interval)
882 2aaa1336 John Giannelos
883 2aaa1336 John Giannelos
        self.assertTrue(connected)
884 8252d64f John Giannelos
885 9e4682b5 John Giannelos
    def test_002_connect_to_network(self):
886 4573ea07 John Giannelos
        """Test connect VMs to network"""
887 9e4682b5 John Giannelos
888 f89d0238 John Giannelos
        log.info("Connect VMs to private network")
889 f89d0238 John Giannelos
890 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['A'], self.networkid)
891 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['B'], self.networkid)
892 8252d64f John Giannelos
893 65462ca9 John Giannelos
        #Insist on connecting until action timeout
894 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
895 9e4682b5 John Giannelos
896 65462ca9 John Giannelos
        while True:
897 2aaa1336 John Giannelos
898 2aaa1336 John Giannelos
            netsA=[x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
899 2aaa1336 John Giannelos
            netsB=[x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
900 2aaa1336 John Giannelos
901 2aaa1336 John Giannelos
            if (self.networkid in netsA) and (self.networkid in netsB):
902 65462ca9 John Giannelos
                conn_exists = True
903 de2461ec John Giannelos
                break
904 de2461ec John Giannelos
            elif time.time() > fail_tmout:
905 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
906 65462ca9 John Giannelos
            else:
907 65462ca9 John Giannelos
                time.sleep(self.query_interval)
908 65462ca9 John Giannelos
909 65462ca9 John Giannelos
        self.assertTrue(conn_exists)
910 9e4682b5 John Giannelos
911 88736f65 John Giannelos
    def test_002a_reboot(self):
912 f89d0238 John Giannelos
        """Rebooting server A"""
913 f89d0238 John Giannelos
914 f89d0238 John Giannelos
        log.info("Rebooting server A")
915 f89d0238 John Giannelos
916 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['A'])
917 8252d64f John Giannelos
918 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
919 4573ea07 John Giannelos
        while True:
920 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
921 4573ea07 John Giannelos
            status = d['status']
922 81e8cbf6 John Giannelos
            if status == 'STOPPED':
923 81e8cbf6 John Giannelos
                break
924 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
925 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
926 81e8cbf6 John Giannelos
            else:
927 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
928 81e8cbf6 John Giannelos
929 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['A'])
930 81e8cbf6 John Giannelos
931 81e8cbf6 John Giannelos
        while True:
932 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
933 81e8cbf6 John Giannelos
            status = d['status']
934 4573ea07 John Giannelos
            if status == 'ACTIVE':
935 4573ea07 John Giannelos
                active = True
936 4573ea07 John Giannelos
                break
937 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
938 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
939 4573ea07 John Giannelos
            else:
940 4573ea07 John Giannelos
                time.sleep(self.query_interval)
941 8252d64f John Giannelos
942 4573ea07 John Giannelos
        self.assertTrue(active)
943 88736f65 John Giannelos
944 4573ea07 John Giannelos
    def test_002b_ping_server_A(self):
945 9b013c3a John Giannelos
        "Test if server A responds to IPv4 pings"
946 4573ea07 John Giannelos
947 9b013c3a John Giannelos
        log.info("Testing if server A responds to IPv4 pings ")
948 f89d0238 John Giannelos
949 88736f65 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
950 88736f65 John Giannelos
        ip = self._get_ipv4(server)
951 8252d64f John Giannelos
952 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
953 8252d64f John Giannelos
954 88736f65 John Giannelos
        s = False
955 88736f65 John Giannelos
956 88736f65 John Giannelos
        while True:
957 88736f65 John Giannelos
958 88736f65 John Giannelos
            if self._ping_once(ip):
959 88736f65 John Giannelos
                s = True
960 88736f65 John Giannelos
                break
961 88736f65 John Giannelos
962 88736f65 John Giannelos
            elif time.time() > fail_tmout:
963 88736f65 John Giannelos
                self.assertLess(time.time(), fail_tmout)
964 88736f65 John Giannelos
965 88736f65 John Giannelos
            else:
966 88736f65 John Giannelos
                time.sleep(self.query_interval)
967 88736f65 John Giannelos
968 88736f65 John Giannelos
        self.assertTrue(s)
969 4573ea07 John Giannelos
970 4573ea07 John Giannelos
    def test_002c_reboot(self):
971 f89d0238 John Giannelos
        """Reboot server B"""
972 f89d0238 John Giannelos
973 f89d0238 John Giannelos
        log.info("Rebooting server B")
974 f89d0238 John Giannelos
975 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['B'])
976 8252d64f John Giannelos
977 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
978 4573ea07 John Giannelos
        while True:
979 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
980 4573ea07 John Giannelos
            status = d['status']
981 81e8cbf6 John Giannelos
            if status == 'STOPPED':
982 81e8cbf6 John Giannelos
                break
983 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
984 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
985 81e8cbf6 John Giannelos
            else:
986 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
987 81e8cbf6 John Giannelos
988 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['B'])
989 81e8cbf6 John Giannelos
990 81e8cbf6 John Giannelos
        while True:
991 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
992 81e8cbf6 John Giannelos
            status = d['status']
993 4573ea07 John Giannelos
            if status == 'ACTIVE':
994 4573ea07 John Giannelos
                active = True
995 4573ea07 John Giannelos
                break
996 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
997 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
998 4573ea07 John Giannelos
            else:
999 4573ea07 John Giannelos
                time.sleep(self.query_interval)
1000 8252d64f John Giannelos
1001 4573ea07 John Giannelos
        self.assertTrue(active)
1002 8252d64f John Giannelos
1003 88736f65 John Giannelos
    def test_002d_ping_server_B(self):
1004 9b013c3a John Giannelos
        """Test if server B responds to IPv4 pings"""
1005 4573ea07 John Giannelos
1006 9b013c3a John Giannelos
        log.info("Testing if server B responds to IPv4 pings")
1007 88736f65 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1008 88736f65 John Giannelos
        ip = self._get_ipv4(server)
1009 8252d64f John Giannelos
1010 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1011 8252d64f John Giannelos
1012 88736f65 John Giannelos
        s = False
1013 88736f65 John Giannelos
1014 88736f65 John Giannelos
        while True:
1015 88736f65 John Giannelos
            if self._ping_once(ip):
1016 88736f65 John Giannelos
                s = True
1017 88736f65 John Giannelos
                break
1018 88736f65 John Giannelos
1019 88736f65 John Giannelos
            elif time.time() > fail_tmout:
1020 88736f65 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1021 88736f65 John Giannelos
1022 88736f65 John Giannelos
            else:
1023 88736f65 John Giannelos
                time.sleep(self.query_interval)
1024 88736f65 John Giannelos
1025 88736f65 John Giannelos
        self.assertTrue(s)
1026 88736f65 John Giannelos
1027 88736f65 John Giannelos
    def test_003a_setup_interface_A(self):
1028 f89d0238 John Giannelos
        """Set up eth1 for server A"""
1029 f89d0238 John Giannelos
1030 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1031 e49bdb7c John Giannelos
1032 f89d0238 John Giannelos
        log.info("Setting up interface eth1 for server A")
1033 ae139e8a John Giannelos
1034 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1035 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1036 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1037 8252d64f John Giannelos
1038 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1039 d5cc50b3 John Giannelos
        userlist = users.split()
1040 d5cc50b3 John Giannelos
1041 d5cc50b3 John Giannelos
        if "root" in userlist:
1042 d5cc50b3 John Giannelos
            loginname = "root"
1043 d5cc50b3 John Giannelos
        elif users == None:
1044 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1045 d5cc50b3 John Giannelos
        else:
1046 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1047 1b40b5e3 John Giannelos
1048 ae139e8a John Giannelos
        hostip = self._get_ipv4(server)
1049 740a5649 John Giannelos
        myPass = self.password['A']
1050 8252d64f John Giannelos
1051 2bcfb712 John Giannelos
        log.info("SSH in server A as %s/%s" % (loginname, myPass))
1052 8252d64f John Giannelos
1053 88736f65 John Giannelos
        res = False
1054 1b40b5e3 John Giannelos
1055 d5cc50b3 John Giannelos
        if loginname != "root":
1056 88736f65 John Giannelos
            with settings(
1057 33ae1493 John Giannelos
                hide('warnings', 'running'),
1058 8252d64f John Giannelos
                warn_only=True,
1059 8252d64f John Giannelos
                host_string=hostip,
1060 8252d64f John Giannelos
                user=loginname, password=myPass
1061 88736f65 John Giannelos
                ):
1062 88736f65 John Giannelos
1063 2aaa1336 John Giannelos
                if len(sudo('ifconfig eth1 10.0.0.5')) == 0:
1064 88736f65 John Giannelos
                    res = True
1065 8252d64f John Giannelos
1066 ae139e8a John Giannelos
        else:
1067 ae139e8a John Giannelos
            with settings(
1068 33ae1493 John Giannelos
                hide('warnings', 'running'),
1069 8252d64f John Giannelos
                warn_only=True,
1070 8252d64f John Giannelos
                host_string=hostip,
1071 8252d64f John Giannelos
                user=loginname, password=myPass
1072 ae139e8a John Giannelos
                ):
1073 4573ea07 John Giannelos
1074 2aaa1336 John Giannelos
                if len(run('ifconfig eth1 10.0.0.5')) == 0:
1075 ae139e8a John Giannelos
                    res = True
1076 88736f65 John Giannelos
1077 88736f65 John Giannelos
        self.assertTrue(res)
1078 1b40b5e3 John Giannelos
1079 88736f65 John Giannelos
    def test_003b_setup_interface_B(self):
1080 f89d0238 John Giannelos
        """Setup eth1 for server B"""
1081 1b40b5e3 John Giannelos
1082 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1083 e49bdb7c John Giannelos
1084 f89d0238 John Giannelos
        log.info("Setting up interface eth1 for server B")
1085 ae139e8a John Giannelos
1086 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1087 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1088 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1089 8252d64f John Giannelos
1090 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1091 d5cc50b3 John Giannelos
        userlist = users.split()
1092 d5cc50b3 John Giannelos
1093 d5cc50b3 John Giannelos
        if "root" in userlist:
1094 d5cc50b3 John Giannelos
            loginname = "root"
1095 d5cc50b3 John Giannelos
        elif users == None:
1096 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1097 d5cc50b3 John Giannelos
        else:
1098 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1099 d5cc50b3 John Giannelos
1100 d5cc50b3 John Giannelos
        hostip = self._get_ipv4(server)
1101 740a5649 John Giannelos
        myPass = self.password['B']
1102 740a5649 John Giannelos
1103 2bcfb712 John Giannelos
        log.info("SSH in server B as %s/%s" % (loginname, myPass))
1104 1b40b5e3 John Giannelos
1105 88736f65 John Giannelos
        res = False
1106 88736f65 John Giannelos
1107 d5cc50b3 John Giannelos
        if loginname != "root":
1108 88736f65 John Giannelos
            with settings(
1109 33ae1493 John Giannelos
                hide('warnings', 'running'),
1110 8252d64f John Giannelos
                warn_only=True,
1111 8252d64f John Giannelos
                host_string=hostip,
1112 8252d64f John Giannelos
                user=loginname, password=myPass
1113 88736f65 John Giannelos
                ):
1114 8252d64f John Giannelos
1115 2aaa1336 John Giannelos
                if len(sudo('ifconfig eth1 10.0.0.6')) == 0:
1116 88736f65 John Giannelos
                    res = True
1117 8252d64f John Giannelos
1118 2bcfb712 John Giannelos
        else:
1119 ae139e8a John Giannelos
            with settings(
1120 33ae1493 John Giannelos
                hide('warnings', 'running'),
1121 8252d64f John Giannelos
                warn_only=True,
1122 8252d64f John Giannelos
                host_string=hostip,
1123 8252d64f John Giannelos
                user=loginname, password=myPass
1124 ae139e8a John Giannelos
                ):
1125 ae139e8a John Giannelos
1126 2aaa1336 John Giannelos
                if len(run('ifconfig eth1 10.0.0.6')) == 0:
1127 ae139e8a John Giannelos
                    res = True
1128 ae139e8a John Giannelos
1129 88736f65 John Giannelos
        self.assertTrue(res)
1130 ae139e8a John Giannelos
1131 88736f65 John Giannelos
    def test_003c_test_connection_exists(self):
1132 4573ea07 John Giannelos
        """Ping server B from server A to test if connection exists"""
1133 1b40b5e3 John Giannelos
1134 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1135 e49bdb7c John Giannelos
1136 f89d0238 John Giannelos
        log.info("Testing if server A is actually connected to server B")
1137 f89d0238 John Giannelos
1138 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1139 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1140 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1141 1b40b5e3 John Giannelos
        hostip = self._get_ipv4(server)
1142 d5cc50b3 John Giannelos
1143 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1144 d5cc50b3 John Giannelos
        userlist = users.split()
1145 d5cc50b3 John Giannelos
1146 d5cc50b3 John Giannelos
        if "root" in userlist:
1147 d5cc50b3 John Giannelos
            loginname = "root"
1148 d5cc50b3 John Giannelos
        elif users == None:
1149 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1150 d5cc50b3 John Giannelos
        else:
1151 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1152 1b40b5e3 John Giannelos
1153 88736f65 John Giannelos
        myPass = self.password['A']
1154 88736f65 John Giannelos
1155 1b40b5e3 John Giannelos
        try:
1156 1b40b5e3 John Giannelos
            ssh = paramiko.SSHClient()
1157 1b40b5e3 John Giannelos
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
1158 8252d64f John Giannelos
            ssh.connect(hostip, username=loginname, password=myPass)
1159 1b40b5e3 John Giannelos
        except socket.error:
1160 1b40b5e3 John Giannelos
            raise AssertionError
1161 1b40b5e3 John Giannelos
1162 2aaa1336 John Giannelos
        cmd = "if ping -c 2 -w 3 10.0.0.6 >/dev/null; \
1163 8252d64f John Giannelos
               then echo \'True\'; fi;"
1164 1b40b5e3 John Giannelos
        stdin, stdout, stderr = ssh.exec_command(cmd)
1165 1b40b5e3 John Giannelos
        lines = stdout.readlines()
1166 1b40b5e3 John Giannelos
1167 740a5649 John Giannelos
        exists = False
1168 4573ea07 John Giannelos
1169 88736f65 John Giannelos
        if 'True\n' in lines:
1170 88736f65 John Giannelos
            exists = True
1171 1b40b5e3 John Giannelos
1172 1b40b5e3 John Giannelos
        self.assertTrue(exists)
1173 1b40b5e3 John Giannelos
1174 88736f65 John Giannelos
    def test_004_disconnect_from_network(self):
1175 4573ea07 John Giannelos
        "Disconnecting server A and B from network"
1176 4573ea07 John Giannelos
1177 f89d0238 John Giannelos
        log.info("Disconnecting servers from private network")
1178 f89d0238 John Giannelos
1179 f97dce4d John Giannelos
        prev_state = self.client.get_network_details(self.networkid)
1180 2aaa1336 John Giannelos
        prev_nics = prev_state['attachments']['values']
1181 2aaa1336 John Giannelos
        prev_conn = len(prev_nics)
1182 2aaa1336 John Giannelos
1183 2aaa1336 John Giannelos
        nicsA=[x['id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
1184 2aaa1336 John Giannelos
        nicsB=[x['id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
1185 2aaa1336 John Giannelos
1186 2aaa1336 John Giannelos
        for nic in prev_nics:
1187 2aaa1336 John Giannelos
            if nic in nicsA:
1188 2aaa1336 John Giannelos
                self.client.disconnect_server(self.serverid['A'], nic)
1189 2aaa1336 John Giannelos
            if nic in nicsB:
1190 2aaa1336 John Giannelos
                self.client.disconnect_server(self.serverid['B'], nic)
1191 e94a9d8c John Giannelos
1192 f97dce4d John Giannelos
1193 65462ca9 John Giannelos
        #Insist on deleting until action timeout
1194 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1195 9e4682b5 John Giannelos
1196 65462ca9 John Giannelos
        while True:
1197 2aaa1336 John Giannelos
1198 2aaa1336 John Giannelos
            netsA=[x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
1199 2aaa1336 John Giannelos
            netsB=[x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
1200 2aaa1336 John Giannelos
1201 2aaa1336 John Giannelos
1202 de2461ec John Giannelos
            connected = (self.client.get_network_details(self.networkid))
1203 2aaa1336 John Giannelos
            connections = connected['attachments']['values']
1204 2aaa1336 John Giannelos
            if (self.networkid not in netsA) and (self.networkid not in netsB):
1205 65462ca9 John Giannelos
                conn_exists = False
1206 de2461ec John Giannelos
                break
1207 de2461ec John Giannelos
            elif time.time() > fail_tmout:
1208 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1209 65462ca9 John Giannelos
            else:
1210 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1211 65462ca9 John Giannelos
1212 65462ca9 John Giannelos
        self.assertFalse(conn_exists)
1213 9e4682b5 John Giannelos
1214 88736f65 John Giannelos
    def test_005_destroy_network(self):
1215 e94a9d8c John Giannelos
        """Test submit delete network request"""
1216 f89d0238 John Giannelos
1217 f89d0238 John Giannelos
        log.info("Submitting delete network request")
1218 f89d0238 John Giannelos
1219 8252d64f John Giannelos
        self.client.delete_network(self.networkid)
1220 2aaa1336 John Giannelos
        
1221 2aaa1336 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1222 2aaa1336 John Giannelos
1223 2aaa1336 John Giannelos
        while True:
1224 e94a9d8c John Giannelos
1225 2aaa1336 John Giannelos
            curr_net = []
1226 2aaa1336 John Giannelos
            networks = self.client.list_networks()
1227 2aaa1336 John Giannelos
1228 2aaa1336 John Giannelos
            for net in networks:
1229 2aaa1336 John Giannelos
                curr_net.append(net['id'])
1230 2aaa1336 John Giannelos
1231 2aaa1336 John Giannelos
            if self.networkid not in curr_net:
1232 2aaa1336 John Giannelos
                self.assertTrue(self.networkid not in curr_net)
1233 2aaa1336 John Giannelos
                break
1234 65462ca9 John Giannelos
1235 2aaa1336 John Giannelos
            elif time.time() > fail_tmout:
1236 2aaa1336 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1237 2aaa1336 John Giannelos
1238 2aaa1336 John Giannelos
            else:
1239 2aaa1336 John Giannelos
                time.sleep(self.query_interval)
1240 2aaa1336 John Giannelos
1241 2aaa1336 John Giannelos
                
1242 8252d64f John Giannelos
1243 88736f65 John Giannelos
    def test_006_cleanup_servers(self):
1244 65462ca9 John Giannelos
        """Cleanup servers created for this test"""
1245 f89d0238 John Giannelos
1246 f89d0238 John Giannelos
        log.info("Delete servers created for this test")
1247 f89d0238 John Giannelos
1248 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['A'])
1249 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['B'])
1250 91de9b55 John Giannelos
1251 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1252 65462ca9 John Giannelos
1253 65462ca9 John Giannelos
        #Ensure server gets deleted
1254 8252d64f John Giannelos
        status = dict()
1255 91de9b55 John Giannelos
1256 65462ca9 John Giannelos
        while True:
1257 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['A'])
1258 91de9b55 John Giannelos
            status['A'] = details['status']
1259 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['B'])
1260 91de9b55 John Giannelos
            status['B'] = details['status']
1261 91de9b55 John Giannelos
            if (status['A'] == 'DELETED') and (status['B'] == 'DELETED'):
1262 65462ca9 John Giannelos
                deleted = True
1263 de2461ec John Giannelos
                break
1264 8252d64f John Giannelos
            elif time.time() > fail_tmout:
1265 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1266 65462ca9 John Giannelos
            else:
1267 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1268 8252d64f John Giannelos
1269 65462ca9 John Giannelos
        self.assertTrue(deleted)
1270 e94a9d8c John Giannelos
1271 4573ea07 John Giannelos
1272 21bbbc9b Vangelis Koukis
class TestRunnerProcess(Process):
1273 21bbbc9b Vangelis Koukis
    """A distinct process used to execute part of the tests in parallel"""
1274 21bbbc9b Vangelis Koukis
    def __init__(self, **kw):
1275 21bbbc9b Vangelis Koukis
        Process.__init__(self, **kw)
1276 96da37c8 John Giannelos
        kwargs = kw["kwargs"]
1277 21bbbc9b Vangelis Koukis
        self.testq = kwargs["testq"]
1278 2aaa1336 John Giannelos
        self.worker_folder = kwargs["worker_folder"]
1279 21bbbc9b Vangelis Koukis
1280 21bbbc9b Vangelis Koukis
    def run(self):
1281 21bbbc9b Vangelis Koukis
        # Make sure this test runner process dies with the parent
1282 21bbbc9b Vangelis Koukis
        # and is not left behind.
1283 21bbbc9b Vangelis Koukis
        #
1284 21bbbc9b Vangelis Koukis
        # WARNING: This uses the prctl(2) call and is
1285 21bbbc9b Vangelis Koukis
        # Linux-specific.
1286 2aaa1336 John Giannelos
1287 21bbbc9b Vangelis Koukis
        prctl.set_pdeathsig(signal.SIGHUP)
1288 21bbbc9b Vangelis Koukis
1289 2aaa1336 John Giannelos
        multi = logging.getLogger("multiprocess")
1290 2aaa1336 John Giannelos
1291 21bbbc9b Vangelis Koukis
        while True:
1292 2aaa1336 John Giannelos
            multi.debug("I am process %d, GETting from queue is %s" %
1293 2aaa1336 John Giannelos
                     (os.getpid(), self.testq))
1294 21bbbc9b Vangelis Koukis
            msg = self.testq.get()
1295 2aaa1336 John Giannelos
1296 2aaa1336 John Giannelos
            multi.debug("Dequeued msg: %s" % msg)
1297 21bbbc9b Vangelis Koukis
1298 21bbbc9b Vangelis Koukis
            if msg == "TEST_RUNNER_TERMINATE":
1299 21bbbc9b Vangelis Koukis
                raise SystemExit
1300 2aaa1336 John Giannelos
1301 21bbbc9b Vangelis Koukis
            elif issubclass(msg, unittest.TestCase):
1302 21bbbc9b Vangelis Koukis
                # Assemble a TestSuite, and run it
1303 2aaa1336 John Giannelos
1304 2aaa1336 John Giannelos
                log_file = os.path.join(self.worker_folder, 'details_' +
1305 2aaa1336 John Giannelos
                                        (msg.__name__) + "_" +
1306 2aaa1336 John Giannelos
                                        TEST_RUN_ID + '.log')
1307 2aaa1336 John Giannelos
                
1308 2aaa1336 John Giannelos
                fail_file = os.path.join(self.worker_folder, 'failed_' +
1309 2aaa1336 John Giannelos
                                         (msg.__name__) + "_" +
1310 2aaa1336 John Giannelos
                                         TEST_RUN_ID + '.log')
1311 2aaa1336 John Giannelos
                error_file = os.path.join(self.worker_folder, 'error_' +
1312 2aaa1336 John Giannelos
                                          (msg.__name__) + "_" +
1313 2aaa1336 John Giannelos
                                          TEST_RUN_ID + '.log')
1314 2aaa1336 John Giannelos
1315 2aaa1336 John Giannelos
                f = open(log_file, 'w')
1316 2aaa1336 John Giannelos
                fail = open(fail_file,'w')
1317 2aaa1336 John Giannelos
                error = open(error_file, 'w')
1318 2aaa1336 John Giannelos
1319 2aaa1336 John Giannelos
                log.info(yellow + '* Starting testcase: %s' % msg + normal)
1320 2aaa1336 John Giannelos
1321 2aaa1336 John Giannelos
                runner = unittest.TextTestRunner(f, verbosity=2, failfast = True)
1322 21bbbc9b Vangelis Koukis
                suite = unittest.TestLoader().loadTestsFromTestCase(msg)
1323 2aaa1336 John Giannelos
                result = runner.run(suite)
1324 2aaa1336 John Giannelos
1325 2aaa1336 John Giannelos
                for res in result.errors:
1326 2aaa1336 John Giannelos
                    log.error("snf-burnin encountered an error in " \
1327 2aaa1336 John Giannelos
                                  "testcase: %s" %msg)
1328 2aaa1336 John Giannelos
                    log.error("See log for details")
1329 2aaa1336 John Giannelos
                    error.write(str(res[0]) + '\n')
1330 2aaa1336 John Giannelos
                    error.write(str(res[0].shortDescription()) + '\n')
1331 2aaa1336 John Giannelos
                    error.write('\n')
1332 2aaa1336 John Giannelos
1333 2aaa1336 John Giannelos
                for res in result.failures:
1334 2aaa1336 John Giannelos
                    log.error("snf-burnin failed in testcase: %s" %msg)
1335 2aaa1336 John Giannelos
                    log.error("See log for details")
1336 2aaa1336 John Giannelos
                    fail.write(str(res[0]) + '\n')
1337 2aaa1336 John Giannelos
                    fail.write(str(res[0].shortDescription()) + '\n')
1338 2aaa1336 John Giannelos
                    fail.write('\n')
1339 2aaa1336 John Giannelos
                    if NOFAILFAST == False:
1340 2aaa1336 John Giannelos
                        sys.exit()
1341 2aaa1336 John Giannelos
1342 2aaa1336 John Giannelos
                if (len(result.failures) == 0) and (len(result.errors) == 0):
1343 2aaa1336 John Giannelos
                    log.debug("Passed testcase: %s" %msg)
1344 2aaa1336 John Giannelos
1345 2aaa1336 John Giannelos
                f.close()
1346 2aaa1336 John Giannelos
                fail.close()
1347 2aaa1336 John Giannelos
                error.close()
1348 2aaa1336 John Giannelos
1349 2aaa1336 John Giannelos
1350 21bbbc9b Vangelis Koukis
            else:
1351 21bbbc9b Vangelis Koukis
                raise Exception("Cannot handle msg: %s" % msg)
1352 21bbbc9b Vangelis Koukis
1353 21bbbc9b Vangelis Koukis
1354 2aaa1336 John Giannelos
def _run_cases_in_parallel(cases, fanout, image_folder):
1355 21bbbc9b Vangelis Koukis
    """Run instances of TestCase in parallel, in a number of distinct processes
1356 21bbbc9b Vangelis Koukis

1357 21bbbc9b Vangelis Koukis
    The cases iterable specifies the TestCases to be executed in parallel,
1358 21bbbc9b Vangelis Koukis
    by test runners running in distinct processes.
1359 21bbbc9b Vangelis Koukis
    The fanout parameter specifies the number of processes to spawn,
1360 21bbbc9b Vangelis Koukis
    and defaults to 1.
1361 21bbbc9b Vangelis Koukis
    The runner argument specifies the test runner class to use inside each
1362 21bbbc9b Vangelis Koukis
    runner process.
1363 21bbbc9b Vangelis Koukis

1364 21bbbc9b Vangelis Koukis
    """
1365 2aaa1336 John Giannelos
    
1366 2aaa1336 John Giannelos
    multi = logging.getLogger("multiprocess")
1367 2aaa1336 John Giannelos
    handler = logging.StreamHandler()
1368 2aaa1336 John Giannelos
    multi.addHandler(handler)
1369 21bbbc9b Vangelis Koukis
1370 2aaa1336 John Giannelos
    if VERBOSE:
1371 2aaa1336 John Giannelos
        multi.setLevel(logging.DEBUG)
1372 2aaa1336 John Giannelos
    else:
1373 2aaa1336 John Giannelos
        multi.setLevel(logging.INFO)
1374 2aaa1336 John Giannelos
1375 2aaa1336 John Giannelos
    testq = []
1376 2aaa1336 John Giannelos
    worker_folder = []
1377 21bbbc9b Vangelis Koukis
    runners = []
1378 2aaa1336 John Giannelos
1379 2aaa1336 John Giannelos
    for i in xrange(0,fanout):
1380 2aaa1336 John Giannelos
        testq.append(Queue())
1381 2aaa1336 John Giannelos
        worker_folder.append(os.path.join(image_folder, 'process'+str(i)))
1382 2aaa1336 John Giannelos
        os.mkdir(worker_folder[i])
1383 2aaa1336 John Giannelos
1384 21bbbc9b Vangelis Koukis
    for i in xrange(0, fanout):
1385 2aaa1336 John Giannelos
        kwargs = dict(testq=testq[i], worker_folder=worker_folder[i])
1386 21bbbc9b Vangelis Koukis
        runners.append(TestRunnerProcess(kwargs=kwargs))
1387 21bbbc9b Vangelis Koukis
1388 2aaa1336 John Giannelos
    multi.debug("Spawning %d test runner processes" %len(runners))
1389 2aaa1336 John Giannelos
1390 21bbbc9b Vangelis Koukis
    for p in runners:
1391 21bbbc9b Vangelis Koukis
        p.start()
1392 21bbbc9b Vangelis Koukis
1393 21bbbc9b Vangelis Koukis
    # Enqueue test cases
1394 2aaa1336 John Giannelos
    for i in xrange(0, fanout):
1395 2aaa1336 John Giannelos
        map(testq[i].put, cases)
1396 2aaa1336 John Giannelos
        testq[i].put("TEST_RUNNER_TERMINATE")
1397 2aaa1336 John Giannelos
1398 2aaa1336 John Giannelos
    multi.debug("Spawned %d test runners, PIDs are %s" %
1399 2aaa1336 John Giannelos
              (len(runners), [p.pid for p in runners]))
1400 21bbbc9b Vangelis Koukis
1401 2aaa1336 John Giannelos
    multi.debug("Joining %d processes" % len(runners))
1402 2aaa1336 John Giannelos
    
1403 21bbbc9b Vangelis Koukis
    for p in runners:
1404 21bbbc9b Vangelis Koukis
        p.join()
1405 2aaa1336 John Giannelos
1406 2aaa1336 John Giannelos
    multi.debug("Done joining %d processes" % len(runners))
1407 4fdd25ab Vangelis Koukis
1408 5a140b23 Vangelis Koukis
1409 5a140b23 Vangelis Koukis
def _spawn_server_test_case(**kwargs):
1410 5a140b23 Vangelis Koukis
    """Construct a new unit test case class from SpawnServerTestCase"""
1411 5a140b23 Vangelis Koukis
1412 c1d11f96 John Giannelos
    name = "SpawnServerTestCase_%s" % kwargs["imageid"]
1413 5a140b23 Vangelis Koukis
    cls = type(name, (SpawnServerTestCase,), kwargs)
1414 5a140b23 Vangelis Koukis
1415 5a140b23 Vangelis Koukis
    # Patch extra parameters into test names by manipulating method docstrings
1416 5a140b23 Vangelis Koukis
    for (mname, m) in \
1417 5a140b23 Vangelis Koukis
        inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
1418 74ec726f John Giannelos
        if hasattr(m, __doc__):
1419 74ec726f John Giannelos
            m.__func__.__doc__ = "[%s] %s" % (imagename, m.__doc__)
1420 e72bcf60 Vangelis Koukis
1421 e72bcf60 Vangelis Koukis
    # Make sure the class can be pickled, by listing it among
1422 e72bcf60 Vangelis Koukis
    # the attributes of __main__. A PicklingError is raised otherwise.
1423 2aaa1336 John Giannelos
1424 2aaa1336 John Giannelos
    thismodule = sys.modules[__name__]
1425 2aaa1336 John Giannelos
    setattr(thismodule, name, cls)
1426 8252d64f John Giannelos
    return cls
1427 65462ca9 John Giannelos
1428 2bcfb712 John Giannelos
1429 65462ca9 John Giannelos
def _spawn_network_test_case(**kwargs):
1430 65462ca9 John Giannelos
    """Construct a new unit test case class from NetworkTestCase"""
1431 65462ca9 John Giannelos
1432 2bcfb712 John Giannelos
    name = "NetworkTestCase" + TEST_RUN_ID
1433 65462ca9 John Giannelos
    cls = type(name, (NetworkTestCase,), kwargs)
1434 65462ca9 John Giannelos
1435 65462ca9 John Giannelos
    # Make sure the class can be pickled, by listing it among
1436 65462ca9 John Giannelos
    # the attributes of __main__. A PicklingError is raised otherwise.
1437 2aaa1336 John Giannelos
    
1438 2aaa1336 John Giannelos
    thismodule = sys.modules[__name__]
1439 2aaa1336 John Giannelos
    setattr(thismodule, name, cls)
1440 8252d64f John Giannelos
    return cls
1441 5a140b23 Vangelis Koukis
1442 5a140b23 Vangelis Koukis
1443 5a140b23 Vangelis Koukis
def cleanup_servers(delete_stale=False):
1444 74193008 John Giannelos
1445 567ffb85 John Giannelos
    c = ComputeClient(API, TOKEN)
1446 74193008 John Giannelos
1447 5a140b23 Vangelis Koukis
    servers = c.list_servers()
1448 5a140b23 Vangelis Koukis
    stale = [s for s in servers if s["name"].startswith(SNF_TEST_PREFIX)]
1449 5a140b23 Vangelis Koukis
1450 4fdd25ab Vangelis Koukis
    if len(stale) == 0:
1451 4fdd25ab Vangelis Koukis
        return
1452 4fdd25ab Vangelis Koukis
1453 746540cd John Giannelos
    print >> sys.stderr, yellow + "Found these stale servers from previous runs:" + normal
1454 5a140b23 Vangelis Koukis
    print "    " + \
1455 21bbbc9b Vangelis Koukis
          "\n    ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
1456 5a140b23 Vangelis Koukis
1457 5a140b23 Vangelis Koukis
    if delete_stale:
1458 5a140b23 Vangelis Koukis
        print >> sys.stderr, "Deleting %d stale servers:" % len(stale)
1459 5a140b23 Vangelis Koukis
        for server in stale:
1460 21bbbc9b Vangelis Koukis
            c.delete_server(server["id"])
1461 746540cd John Giannelos
        print >> sys.stderr, green + "    ...done" + normal
1462 5a140b23 Vangelis Koukis
    else:
1463 5a140b23 Vangelis Koukis
        print >> sys.stderr, "Use --delete-stale to delete them."
1464 5a140b23 Vangelis Koukis
1465 2bcfb712 John Giannelos
1466 2aaa1336 John Giannelos
def cleanup_networks(action_timeout, query_interval,delete_stale=False):
1467 2aaa1336 John Giannelos
    def isSnfTest(s):
1468 2aaa1336 John Giannelos
        if s.find(SNF_TEST_PREFIX) == -1:
1469 2aaa1336 John Giannelos
            return False
1470 2aaa1336 John Giannelos
        else:
1471 2aaa1336 John Giannelos
            return True
1472 74ec726f John Giannelos
1473 74ec726f John Giannelos
    c = CycladesClient(API, TOKEN)
1474 2aaa1336 John Giannelos
    
1475 74ec726f John Giannelos
    networks = c.list_networks()
1476 74ec726f John Giannelos
    stale = [n for n in networks if n["name"].startswith(SNF_TEST_PREFIX)]
1477 74ec726f John Giannelos
1478 74ec726f John Giannelos
    if len(stale) == 0:
1479 74ec726f John Giannelos
        return
1480 2aaa1336 John Giannelos
    
1481 2aaa1336 John Giannelos
    fail_tmout = time.time() + action_timeout
1482 2aaa1336 John Giannelos
    while True:
1483 2aaa1336 John Giannelos
        servers = c.list_servers()
1484 2aaa1336 John Giannelos
        staleServers = [s for s in servers if s["name"].startswith(SNF_TEST_PREFIX)]
1485 2aaa1336 John Giannelos
        if len(staleServers) == 0:
1486 2aaa1336 John Giannelos
            break
1487 2aaa1336 John Giannelos
        elif time.time() > fail_tmout:
1488 2aaa1336 John Giannelos
            log.error("Stale servers not deleted from previous run")
1489 2aaa1336 John Giannelos
            sys.exit()
1490 2aaa1336 John Giannelos
        else:
1491 2aaa1336 John Giannelos
            time.sleep(query_interval)
1492 74ec726f John Giannelos
1493 746540cd John Giannelos
    print >> sys.stderr, yellow + "Found these stale networks from previous runs:" + normal
1494 74ec726f John Giannelos
    print "    " + \
1495 74ec726f John Giannelos
          "\n    ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
1496 74ec726f John Giannelos
1497 74ec726f John Giannelos
    if delete_stale:
1498 74ec726f John Giannelos
        print >> sys.stderr, "Deleting %d stale networks:" % len(stale)
1499 74ec726f John Giannelos
        for network in stale:
1500 74ec726f John Giannelos
            c.delete_network(network["id"])
1501 746540cd John Giannelos
        print >> sys.stderr, green + "    ...done" + normal
1502 74ec726f John Giannelos
    else:
1503 74ec726f John Giannelos
        print >> sys.stderr, "Use --delete-stale to delete them."
1504 74ec726f John Giannelos
1505 746540cd John Giannelos
1506 22efe1fe John Giannelos
def parse_comma(option, opt, value, parser):
1507 746540cd John Giannelos
    tests = set(['all', 'auth', 'images', 'flavors',
1508 22efe1fe John Giannelos
               'servers', 'server_spawn', 'network_spawn'])
1509 22efe1fe John Giannelos
    parse_input = value.split(',')
1510 22efe1fe John Giannelos
1511 22efe1fe John Giannelos
    if not (set(parse_input)).issubset(tests):
1512 22efe1fe John Giannelos
        raise OptionValueError("The selected set of tests is invalid")
1513 22efe1fe John Giannelos
1514 22efe1fe John Giannelos
    setattr(parser.values, option.dest, value.split(','))
1515 22efe1fe John Giannelos
1516 74ec726f John Giannelos
1517 5a140b23 Vangelis Koukis
def parse_arguments(args):
1518 5a140b23 Vangelis Koukis
1519 5a140b23 Vangelis Koukis
    kw = {}
1520 5a140b23 Vangelis Koukis
    kw["usage"] = "%prog [options]"
1521 5a140b23 Vangelis Koukis
    kw["description"] = \
1522 5a140b23 Vangelis Koukis
        "%prog runs a number of test scenarios on a " \
1523 5a140b23 Vangelis Koukis
        "Synnefo deployment."
1524 5a140b23 Vangelis Koukis
1525 5a140b23 Vangelis Koukis
    parser = OptionParser(**kw)
1526 5a140b23 Vangelis Koukis
    parser.disable_interspersed_args()
1527 22efe1fe John Giannelos
1528 21bbbc9b Vangelis Koukis
    parser.add_option("--api",
1529 21bbbc9b Vangelis Koukis
                      action="store", type="string", dest="api",
1530 21bbbc9b Vangelis Koukis
                      help="The API URI to use to reach the Synnefo API",
1531 21bbbc9b Vangelis Koukis
                      default=DEFAULT_API)
1532 946da8b6 John Giannelos
    parser.add_option("--plankton",
1533 946da8b6 John Giannelos
                      action="store", type="string", dest="plankton",
1534 946da8b6 John Giannelos
                      help="The API URI to use to reach the Plankton API",
1535 946da8b6 John Giannelos
                      default=DEFAULT_PLANKTON)
1536 946da8b6 John Giannelos
    parser.add_option("--plankton-user",
1537 946da8b6 John Giannelos
                      action="store", type="string", dest="plankton_user",
1538 946da8b6 John Giannelos
                      help="Owner of system images",
1539 946da8b6 John Giannelos
                      default=DEFAULT_PLANKTON_USER)
1540 21bbbc9b Vangelis Koukis
    parser.add_option("--token",
1541 21bbbc9b Vangelis Koukis
                      action="store", type="string", dest="token",
1542 38d247df Kostas Papadimitriou
                      help="The token to use for authentication to the API")
1543 00f87624 Vangelis Koukis
    parser.add_option("--nofailfast",
1544 00f87624 Vangelis Koukis
                      action="store_true", dest="nofailfast",
1545 00f87624 Vangelis Koukis
                      help="Do not fail immediately if one of the tests " \
1546 00f87624 Vangelis Koukis
                           "fails (EXPERIMENTAL)",
1547 bc14ba88 Vangelis Koukis
                      default=False)
1548 946da8b6 John Giannelos
    parser.add_option("--no-ipv6",
1549 946da8b6 John Giannelos
                      action="store_true", dest="no_ipv6",
1550 946da8b6 John Giannelos
                      help="Disables ipv6 related tests",
1551 946da8b6 John Giannelos
                      default=False)
1552 5a140b23 Vangelis Koukis
    parser.add_option("--action-timeout",
1553 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="action_timeout",
1554 5a140b23 Vangelis Koukis
                      metavar="TIMEOUT",
1555 5a140b23 Vangelis Koukis
                      help="Wait SECONDS seconds for a server action to " \
1556 5a140b23 Vangelis Koukis
                           "complete, then the test is considered failed",
1557 9e4682b5 John Giannelos
                      default=100)
1558 5a140b23 Vangelis Koukis
    parser.add_option("--build-warning",
1559 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="build_warning",
1560 5a140b23 Vangelis Koukis
                      metavar="TIMEOUT",
1561 5a140b23 Vangelis Koukis
                      help="Warn if TIMEOUT seconds have passed and a " \
1562 5a140b23 Vangelis Koukis
                           "build operation is still pending",
1563 5a140b23 Vangelis Koukis
                      default=600)
1564 5a140b23 Vangelis Koukis
    parser.add_option("--build-fail",
1565 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="build_fail",
1566 5a140b23 Vangelis Koukis
                      metavar="BUILD_TIMEOUT",
1567 5a140b23 Vangelis Koukis
                      help="Fail the test if TIMEOUT seconds have passed " \
1568 5a140b23 Vangelis Koukis
                           "and a build operation is still incomplete",
1569 5a140b23 Vangelis Koukis
                      default=900)
1570 5a140b23 Vangelis Koukis
    parser.add_option("--query-interval",
1571 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="query_interval",
1572 5a140b23 Vangelis Koukis
                      metavar="INTERVAL",
1573 5a140b23 Vangelis Koukis
                      help="Query server status when requests are pending " \
1574 5a140b23 Vangelis Koukis
                           "every INTERVAL seconds",
1575 5a140b23 Vangelis Koukis
                      default=3)
1576 21bbbc9b Vangelis Koukis
    parser.add_option("--fanout",
1577 21bbbc9b Vangelis Koukis
                      action="store", type="int", dest="fanout",
1578 5a140b23 Vangelis Koukis
                      metavar="COUNT",
1579 21bbbc9b Vangelis Koukis
                      help="Spawn up to COUNT child processes to execute " \
1580 21bbbc9b Vangelis Koukis
                           "in parallel, essentially have up to COUNT " \
1581 00f87624 Vangelis Koukis
                           "server build requests outstanding (EXPERIMENTAL)",
1582 5a140b23 Vangelis Koukis
                      default=1)
1583 5a140b23 Vangelis Koukis
    parser.add_option("--force-flavor",
1584 5a140b23 Vangelis Koukis
                      action="store", type="int", dest="force_flavorid",
1585 5a140b23 Vangelis Koukis
                      metavar="FLAVOR ID",
1586 5a140b23 Vangelis Koukis
                      help="Force all server creations to use the specified "\
1587 5a140b23 Vangelis Koukis
                           "FLAVOR ID instead of a randomly chosen one, " \
1588 5a140b23 Vangelis Koukis
                           "useful if disk space is scarce",
1589 00f87624 Vangelis Koukis
                      default=None)
1590 7f62a0b5 Vangelis Koukis
    parser.add_option("--image-id",
1591 7f62a0b5 Vangelis Koukis
                      action="store", type="string", dest="force_imageid",
1592 00f87624 Vangelis Koukis
                      metavar="IMAGE ID",
1593 7f62a0b5 Vangelis Koukis
                      help="Test the specified image id, use 'all' to test " \
1594 7f62a0b5 Vangelis Koukis
                           "all available images (mandatory argument)",
1595 00f87624 Vangelis Koukis
                      default=None)
1596 5a140b23 Vangelis Koukis
    parser.add_option("--show-stale",
1597 5a140b23 Vangelis Koukis
                      action="store_true", dest="show_stale",
1598 5a140b23 Vangelis Koukis
                      help="Show stale servers from previous runs, whose "\
1599 21bbbc9b Vangelis Koukis
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1600 5a140b23 Vangelis Koukis
                      default=False)
1601 5a140b23 Vangelis Koukis
    parser.add_option("--delete-stale",
1602 5a140b23 Vangelis Koukis
                      action="store_true", dest="delete_stale",
1603 5a140b23 Vangelis Koukis
                      help="Delete stale servers from previous runs, whose "\
1604 21bbbc9b Vangelis Koukis
                           "name starts with `%s'" % SNF_TEST_PREFIX,
1605 5a140b23 Vangelis Koukis
                      default=False)
1606 9659e075 John Giannelos
    parser.add_option("--force-personality",
1607 65462ca9 John Giannelos
                      action="store", type="string", dest="personality_path",
1608 8252d64f John Giannelos
                      help="Force a personality file injection.\
1609 8252d64f John Giannelos
                            File path required. ",
1610 9659e075 John Giannelos
                      default=None)
1611 74ec726f John Giannelos
    parser.add_option("--log-folder",
1612 74ec726f John Giannelos
                      action="store", type="string", dest="log_folder",
1613 8252d64f John Giannelos
                      help="Define the absolute path where the output \
1614 8252d64f John Giannelos
                            log is stored. ",
1615 2bcfb712 John Giannelos
                      default="/var/log/burnin/")
1616 2aaa1336 John Giannelos
    parser.add_option("--verbose", "-V",
1617 2aaa1336 John Giannelos
                      action="store_true", dest="verbose",
1618 2aaa1336 John Giannelos
                      help="Print detailed output about multiple processes spawning",
1619 2aaa1336 John Giannelos
                      default=False)
1620 22efe1fe John Giannelos
    parser.add_option("--set-tests",
1621 22efe1fe John Giannelos
                      action="callback",
1622 746540cd John Giannelos
                      dest="tests",
1623 22efe1fe John Giannelos
                      type="string",
1624 22efe1fe John Giannelos
                      help='Set comma seperated tests for this run. \
1625 22efe1fe John Giannelos
                            Available tests: auth, images, flavors, \
1626 746540cd John Giannelos
                                             servers, server_spawn, \
1627 746540cd John Giannelos
                                             network_spawn. \
1628 22efe1fe John Giannelos
                            Default = all',
1629 22efe1fe John Giannelos
                      default='all',
1630 22efe1fe John Giannelos
                      callback=parse_comma)
1631 22efe1fe John Giannelos
1632 5a140b23 Vangelis Koukis
    (opts, args) = parser.parse_args(args)
1633 5a140b23 Vangelis Koukis
1634 5a140b23 Vangelis Koukis
    # Verify arguments
1635 5a140b23 Vangelis Koukis
    if opts.delete_stale:
1636 5a140b23 Vangelis Koukis
        opts.show_stale = True
1637 5a140b23 Vangelis Koukis
1638 7f62a0b5 Vangelis Koukis
    if not opts.show_stale:
1639 7f62a0b5 Vangelis Koukis
        if not opts.force_imageid:
1640 746540cd John Giannelos
            print >>sys.stderr, red + "The --image-id argument " \
1641 746540cd John Giannelos
                                       "is mandatory.\n" + normal
1642 22efe1fe John Giannelos
            parser.print_help()
1643 22efe1fe John Giannelos
            sys.exit(1)
1644 22efe1fe John Giannelos
1645 22efe1fe John Giannelos
        if not opts.token:
1646 746540cd John Giannelos
            print >>sys.stderr, red + "The --token argument is " \
1647 746540cd John Giannelos
                                      "mandatory.\n" + normal
1648 7f62a0b5 Vangelis Koukis
            parser.print_help()
1649 7f62a0b5 Vangelis Koukis
            sys.exit(1)
1650 7f62a0b5 Vangelis Koukis
1651 7f62a0b5 Vangelis Koukis
        if opts.force_imageid != 'all':
1652 7f62a0b5 Vangelis Koukis
            try:
1653 99d41650 John Giannelos
                opts.force_imageid = str(opts.force_imageid)
1654 7f62a0b5 Vangelis Koukis
            except ValueError:
1655 746540cd John Giannelos
                print >>sys.stderr, red + "Invalid value specified for" \
1656 746540cd John Giannelos
                    "--image-id. Use a valid id, or `all'." + normal
1657 7f62a0b5 Vangelis Koukis
                sys.exit(1)
1658 7f62a0b5 Vangelis Koukis
1659 5a140b23 Vangelis Koukis
    return (opts, args)
1660 5a140b23 Vangelis Koukis
1661 5a140b23 Vangelis Koukis
1662 5a140b23 Vangelis Koukis
def main():
1663 5a140b23 Vangelis Koukis
    """Assemble test cases into a test suite, and run it
1664 5a140b23 Vangelis Koukis

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

1671 5a140b23 Vangelis Koukis
    """
1672 ae139e8a John Giannelos
1673 5a140b23 Vangelis Koukis
    (opts, args) = parse_arguments(sys.argv[1:])
1674 5a140b23 Vangelis Koukis
1675 2aaa1336 John Giannelos
    global API, TOKEN, PLANKTON, PLANKTON_USER, NO_IPV6, VERBOSE, NOFAILFAST
1676 21bbbc9b Vangelis Koukis
    API = opts.api
1677 21bbbc9b Vangelis Koukis
    TOKEN = opts.token
1678 946da8b6 John Giannelos
    PLANKTON = opts.plankton
1679 946da8b6 John Giannelos
    PLANKTON_USER = opts.plankton_user
1680 946da8b6 John Giannelos
    NO_IPV6 = opts.no_ipv6
1681 2aaa1336 John Giannelos
    VERBOSE = opts.verbose
1682 2aaa1336 John Giannelos
    NOFAILFAST = opts.nofailfast
1683 21bbbc9b Vangelis Koukis
1684 5a140b23 Vangelis Koukis
    # Cleanup stale servers from previous runs
1685 5a140b23 Vangelis Koukis
    if opts.show_stale:
1686 5a140b23 Vangelis Koukis
        cleanup_servers(delete_stale=opts.delete_stale)
1687 2aaa1336 John Giannelos
        cleanup_networks(opts.action_timeout, opts.query_interval, delete_stale=opts.delete_stale)
1688 74ec726f John Giannelos
        return 0
1689 5a140b23 Vangelis Koukis
1690 5a140b23 Vangelis Koukis
    # Initialize a kamaki instance, get flavors, images
1691 96da37c8 John Giannelos
    c = ComputeClient(API, TOKEN)
1692 74193008 John Giannelos
1693 5a140b23 Vangelis Koukis
    DIMAGES = c.list_images(detail=True)
1694 5a140b23 Vangelis Koukis
    DFLAVORS = c.list_flavors(detail=True)
1695 5a140b23 Vangelis Koukis
1696 21bbbc9b Vangelis Koukis
    # FIXME: logging, log, LOG PID, TEST_RUN_ID, arguments
1697 5a140b23 Vangelis Koukis
    # Run them: FIXME: In parallel, FAILEARLY, catchbreak?
1698 5a140b23 Vangelis Koukis
    #unittest.main(verbosity=2, catchbreak=True)
1699 5a140b23 Vangelis Koukis
1700 e94a9d8c John Giannelos
    if opts.force_imageid == 'all':
1701 e94a9d8c John Giannelos
        test_images = DIMAGES
1702 e94a9d8c John Giannelos
    else:
1703 e94a9d8c John Giannelos
        test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
1704 e94a9d8c John Giannelos
1705 81e8cbf6 John Giannelos
    #New folder for log per image
1706 74ec726f John Giannelos
    if not os.path.exists(opts.log_folder):
1707 74ec726f John Giannelos
        os.mkdir(opts.log_folder)
1708 74ec726f John Giannelos
1709 2bcfb712 John Giannelos
    test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
1710 74ec726f John Giannelos
    os.mkdir(test_folder)
1711 81e8cbf6 John Giannelos
1712 00f87624 Vangelis Koukis
    for image in test_images:
1713 8252d64f John Giannelos
1714 99d41650 John Giannelos
        imageid = str(image["id"])
1715 8252d64f John Giannelos
1716 81e8cbf6 John Giannelos
        if opts.force_flavorid:
1717 81e8cbf6 John Giannelos
            flavorid = opts.force_flavorid
1718 81e8cbf6 John Giannelos
        else:
1719 81e8cbf6 John Giannelos
            flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
1720 81e8cbf6 John Giannelos
1721 21bbbc9b Vangelis Koukis
        imagename = image["name"]
1722 8252d64f John Giannelos
1723 567ffb85 John Giannelos
        #Personality dictionary for file injection test
1724 9659e075 John Giannelos
        if opts.personality_path != None:
1725 9659e075 John Giannelos
            f = open(opts.personality_path)
1726 9659e075 John Giannelos
            content = b64encode(f.read())
1727 9659e075 John Giannelos
            personality = []
1728 9659e075 John Giannelos
            st = os.stat(opts.personality_path)
1729 9659e075 John Giannelos
            personality.append({
1730 9659e075 John Giannelos
                    'path': '/root/test_inj_file',
1731 9659e075 John Giannelos
                    'owner': 'root',
1732 9659e075 John Giannelos
                    'group': 'root',
1733 9659e075 John Giannelos
                    'mode': 0x7777 & st.st_mode,
1734 9659e075 John Giannelos
                    'contents': content
1735 9659e075 John Giannelos
                    })
1736 9659e075 John Giannelos
        else:
1737 9659e075 John Giannelos
            personality = None
1738 9659e075 John Giannelos
1739 21bbbc9b Vangelis Koukis
        servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
1740 21bbbc9b Vangelis Koukis
        is_windows = imagename.lower().find("windows") >= 0
1741 8252d64f John Giannelos
1742 8252d64f John Giannelos
        ServerTestCase = _spawn_server_test_case(
1743 8252d64f John Giannelos
            imageid=imageid,
1744 8252d64f John Giannelos
            flavorid=flavorid,
1745 8252d64f John Giannelos
            imagename=imagename,
1746 8252d64f John Giannelos
            personality=personality,
1747 8252d64f John Giannelos
            servername=servername,
1748 8252d64f John Giannelos
            is_windows=is_windows,
1749 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
1750 8252d64f John Giannelos
            build_warning=opts.build_warning,
1751 8252d64f John Giannelos
            build_fail=opts.build_fail,
1752 8252d64f John Giannelos
            query_interval=opts.query_interval,
1753 8252d64f John Giannelos
            )
1754 8252d64f John Giannelos
1755 2aaa1336 John Giannelos
        
1756 8252d64f John Giannelos
        NetworkTestCase = _spawn_network_test_case(
1757 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
1758 8252d64f John Giannelos
            imageid=imageid,
1759 8252d64f John Giannelos
            flavorid=flavorid,
1760 8252d64f John Giannelos
            imagename=imagename,
1761 8252d64f John Giannelos
            query_interval=opts.query_interval,
1762 8252d64f John Giannelos
            )
1763 8252d64f John Giannelos
1764 746540cd John Giannelos
        test_dict = {'auth': UnauthorizedTestCase,
1765 746540cd John Giannelos
                     'images': ImagesTestCase,
1766 746540cd John Giannelos
                     'flavors': FlavorsTestCase,
1767 746540cd John Giannelos
                     'servers': ServersTestCase,
1768 746540cd John Giannelos
                     'server_spawn': ServerTestCase,
1769 746540cd John Giannelos
                     'network_spawn': NetworkTestCase}
1770 22efe1fe John Giannelos
1771 22efe1fe John Giannelos
        seq_cases = []
1772 22efe1fe John Giannelos
        if 'all' in opts.tests:
1773 22efe1fe John Giannelos
            seq_cases = [UnauthorizedTestCase, ImagesTestCase, FlavorsTestCase,
1774 22efe1fe John Giannelos
                         ServersTestCase, ServerTestCase, NetworkTestCase]
1775 22efe1fe John Giannelos
        else:
1776 22efe1fe John Giannelos
            for test in opts.tests:
1777 22efe1fe John Giannelos
                seq_cases.append(test_dict[test])
1778 22efe1fe John Giannelos
1779 8252d64f John Giannelos
        #folder for each image
1780 2bcfb712 John Giannelos
        image_folder = os.path.join(test_folder, imageid)
1781 81e8cbf6 John Giannelos
        os.mkdir(image_folder)
1782 81e8cbf6 John Giannelos
1783 2aaa1336 John Giannelos
        log.info('Parallel spawn:')
1784 2aaa1336 John Giannelos
1785 2aaa1336 John Giannelos
        _run_cases_in_parallel(seq_cases, opts.fanout, image_folder)
1786 746540cd John Giannelos
1787 5a140b23 Vangelis Koukis
if __name__ == "__main__":
1788 5a140b23 Vangelis Koukis
    sys.exit(main())