Statistics
| Branch: | Tag: | Revision:

root / snf-tools / synnefo_tools / burnin.py @ 3b59f34b

History | View | Annotate | Download (64.6 kB)

1 65462ca9 John Giannelos
#!/usr/bin/env python
2 5a140b23 Vangelis Koukis
3 5a140b23 Vangelis Koukis
# Copyright 2011 GRNET S.A. All rights reserved.
4 5a140b23 Vangelis Koukis
#
5 5a140b23 Vangelis Koukis
# Redistribution and use in source and binary forms, with or
6 5a140b23 Vangelis Koukis
# without modification, are permitted provided that the following
7 5a140b23 Vangelis Koukis
# conditions are met:
8 5a140b23 Vangelis Koukis
#
9 5a140b23 Vangelis Koukis
#   1. Redistributions of source code must retain the above
10 5a140b23 Vangelis Koukis
#      copyright notice, this list of conditions and the following
11 5a140b23 Vangelis Koukis
#      disclaimer.
12 5a140b23 Vangelis Koukis
#
13 5a140b23 Vangelis Koukis
#   2. Redistributions in binary form must reproduce the above
14 5a140b23 Vangelis Koukis
#      copyright notice, this list of conditions and the following
15 5a140b23 Vangelis Koukis
#      disclaimer in the documentation and/or other materials
16 5a140b23 Vangelis Koukis
#      provided with the distribution.
17 5a140b23 Vangelis Koukis
#
18 5a140b23 Vangelis Koukis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
19 5a140b23 Vangelis Koukis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 5a140b23 Vangelis Koukis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 5a140b23 Vangelis Koukis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
22 5a140b23 Vangelis Koukis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 5a140b23 Vangelis Koukis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 5a140b23 Vangelis Koukis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
25 5a140b23 Vangelis Koukis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 5a140b23 Vangelis Koukis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 5a140b23 Vangelis Koukis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 5a140b23 Vangelis Koukis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 5a140b23 Vangelis Koukis
# POSSIBILITY OF SUCH DAMAGE.
30 5a140b23 Vangelis Koukis
#
31 5a140b23 Vangelis Koukis
# The views and conclusions contained in the software and
32 5a140b23 Vangelis Koukis
# documentation are those of the authors and should not be
33 5a140b23 Vangelis Koukis
# interpreted as representing official policies, either expressed
34 5a140b23 Vangelis Koukis
# or implied, of GRNET S.A.
35 5a140b23 Vangelis Koukis
36 5a140b23 Vangelis Koukis
"""Perform integration testing on a running Synnefo deployment"""
37 5a140b23 Vangelis Koukis
38 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 66eba2cf John Giannelos
class BurninTestResult(unittest.TextTestResult):
75 66eba2cf John Giannelos
    def addSuccess(self, test):
76 66eba2cf John Giannelos
        super(BurninTestResult, self).addSuccess(test)
77 66eba2cf John Giannelos
        if self.showAll:
78 66eba2cf John Giannelos
            if test.result_dict:
79 66eba2cf John Giannelos
                run_details = test.result_dict
80 66eba2cf John Giannelos
81 66eba2cf John Giannelos
                self.stream.write("\n")
82 66eba2cf John Giannelos
                for i in run_details:
83 66eba2cf John Giannelos
                    self.stream.write("%s : %s \n" % (i, run_details[i]))
84 66eba2cf John Giannelos
                self.stream.write("\n")
85 66eba2cf John Giannelos
86 66eba2cf John Giannelos
        elif self.dots:
87 66eba2cf John Giannelos
            self.stream.write('.')
88 66eba2cf John Giannelos
            self.stream.flush() 
89 66eba2cf John Giannelos
            
90 66eba2cf John Giannelos
    def addError(self, test, err):
91 66eba2cf John Giannelos
        super(BurninTestResult, self).addError(test, err)
92 66eba2cf John Giannelos
        if self.showAll:
93 66eba2cf John Giannelos
            self.stream.writeln("ERROR")
94 66eba2cf John Giannelos
95 66eba2cf John Giannelos
            run_details = test.result_dict
96 66eba2cf John Giannelos
97 66eba2cf John Giannelos
            self.stream.write("\n")
98 66eba2cf John Giannelos
            for i in run_details:
99 66eba2cf John Giannelos
                self.stream.write("%s : %s \n" % (i, run_details[i]))
100 66eba2cf John Giannelos
            self.stream.write("\n")
101 66eba2cf John Giannelos
102 66eba2cf John Giannelos
        elif self.dots:
103 66eba2cf John Giannelos
            self.stream.write('E')
104 66eba2cf John Giannelos
            self.stream.flush()
105 66eba2cf John Giannelos
106 66eba2cf John Giannelos
    def addFailure(self, test, err):
107 66eba2cf John Giannelos
        super(BurninTestResult, self).addFailure(test, err)
108 66eba2cf John Giannelos
        if self.showAll:
109 66eba2cf John Giannelos
            self.stream.writeln("FAIL")
110 66eba2cf John Giannelos
111 66eba2cf John Giannelos
            run_details = test.result_dict
112 66eba2cf John Giannelos
113 66eba2cf John Giannelos
            self.stream.write("\n")
114 66eba2cf John Giannelos
            for i in run_details:
115 66eba2cf John Giannelos
                self.stream.write("%s : %s \n" % (i, run_details[i]))
116 66eba2cf John Giannelos
            self.stream.write("\n")
117 66eba2cf John Giannelos
118 66eba2cf John Giannelos
        elif self.dots:
119 66eba2cf John Giannelos
            self.stream.write('F')
120 66eba2cf John Giannelos
            self.stream.flush()
121 66eba2cf John Giannelos
122 66eba2cf John Giannelos
123 66eba2cf John Giannelos
124 21bbbc9b Vangelis Koukis
API = None
125 21bbbc9b Vangelis Koukis
TOKEN = None
126 567ffb85 John Giannelos
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
127 946da8b6 John Giannelos
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
128 946da8b6 John Giannelos
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
129 38d247df Kostas Papadimitriou
130 5a140b23 Vangelis Koukis
# A unique id identifying this test run
131 21bbbc9b Vangelis Koukis
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
132 21bbbc9b Vangelis Koukis
                                         "%Y%m%d%H%M%S")
133 21bbbc9b Vangelis Koukis
SNF_TEST_PREFIX = "snf-test-"
134 5a140b23 Vangelis Koukis
135 746540cd John Giannelos
red = '\x1b[31m'
136 746540cd John Giannelos
yellow = '\x1b[33m'
137 746540cd John Giannelos
green = '\x1b[32m'
138 746540cd John Giannelos
normal = '\x1b[0m'
139 746540cd John Giannelos
140 746540cd John Giannelos
141 746540cd John Giannelos
class burninFormatter(logging.Formatter):
142 746540cd John Giannelos
143 746540cd John Giannelos
    err_fmt = red + "ERROR: %(msg)s" + normal
144 9b013c3a John Giannelos
    dbg_fmt = green + "* %(msg)s" + normal
145 746540cd John Giannelos
    info_fmt = "%(msg)s"
146 746540cd John Giannelos
147 746540cd John Giannelos
    def __init__(self, fmt="%(levelno)s: %(msg)s"):
148 746540cd John Giannelos
        logging.Formatter.__init__(self, fmt)
149 746540cd John Giannelos
150 746540cd John Giannelos
    def format(self, record):
151 746540cd John Giannelos
152 746540cd John Giannelos
        format_orig = self._fmt
153 746540cd John Giannelos
154 746540cd John Giannelos
        # Replace the original format with one customized by logging level
155 746540cd John Giannelos
        if record.levelno == 10:    # DEBUG
156 746540cd John Giannelos
            self._fmt = burninFormatter.dbg_fmt
157 746540cd John Giannelos
158 746540cd John Giannelos
        elif record.levelno == 20:  # INFO
159 746540cd John Giannelos
            self._fmt = burninFormatter.info_fmt
160 746540cd John Giannelos
161 746540cd John Giannelos
        elif record.levelno == 40:  # ERROR
162 746540cd John Giannelos
            self._fmt = burninFormatter.err_fmt
163 746540cd John Giannelos
164 746540cd John Giannelos
        result = logging.Formatter.format(self, record)
165 746540cd John Giannelos
        self._fmt = format_orig
166 746540cd John Giannelos
167 746540cd John Giannelos
        return result
168 746540cd John Giannelos
169 746540cd John Giannelos
170 00f87624 Vangelis Koukis
log = logging.getLogger("burnin")
171 746540cd John Giannelos
log.setLevel(logging.DEBUG)
172 746540cd John Giannelos
handler = logging.StreamHandler()
173 746540cd John Giannelos
handler.setFormatter(burninFormatter())
174 746540cd John Giannelos
log.addHandler(handler)
175 5a140b23 Vangelis Koukis
176 2bcfb712 John Giannelos
177 5a140b23 Vangelis Koukis
class UnauthorizedTestCase(unittest.TestCase):
178 66eba2cf John Giannelos
179 66eba2cf John Giannelos
    @classmethod
180 66eba2cf John Giannelos
    def setUpClass(cls):
181 66eba2cf John Giannelos
        cls.result_dict = dict()
182 66eba2cf John Giannelos
183 5a140b23 Vangelis Koukis
    def test_unauthorized_access(self):
184 5a140b23 Vangelis Koukis
        """Test access without a valid token fails"""
185 81e8cbf6 John Giannelos
        log.info("Authentication test")
186 81e8cbf6 John Giannelos
187 1c636ad6 John Giannelos
        falseToken = '12345'
188 2bcfb712 John Giannelos
        c = ComputeClient(API, falseToken)
189 1c636ad6 John Giannelos
190 5a140b23 Vangelis Koukis
        with self.assertRaises(ClientError) as cm:
191 5a140b23 Vangelis Koukis
            c.list_servers()
192 21dcb666 John Giannelos
            self.assertEqual(cm.exception.status, 401)
193 5a140b23 Vangelis Koukis
194 5a140b23 Vangelis Koukis
195 5a140b23 Vangelis Koukis
class ImagesTestCase(unittest.TestCase):
196 5a140b23 Vangelis Koukis
    """Test image lists for consistency"""
197 5a140b23 Vangelis Koukis
    @classmethod
198 5a140b23 Vangelis Koukis
    def setUpClass(cls):
199 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of images"""
200 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of images")
201 1c636ad6 John Giannelos
202 846980fe John Giannelos
        cls.client = ComputeClient(API, TOKEN)
203 946da8b6 John Giannelos
        cls.plankton = ImageClient(PLANKTON, TOKEN)
204 946da8b6 John Giannelos
        cls.images = cls.plankton.list_public()
205 946da8b6 John Giannelos
        cls.dimages = cls.plankton.list_public(detail=True)
206 66eba2cf John Giannelos
        cls.result_dict = dict()
207 5a140b23 Vangelis Koukis
208 5a140b23 Vangelis Koukis
    def test_001_list_images(self):
209 5a140b23 Vangelis Koukis
        """Test image list actually returns images"""
210 6207533f John Giannelos
        self.assertGreater(len(self.images), 0)
211 74ec726f John Giannelos
212 5a140b23 Vangelis Koukis
    def test_002_list_images_detailed(self):
213 5a140b23 Vangelis Koukis
        """Test detailed image list is the same length as list"""
214 6207533f John Giannelos
        self.assertEqual(len(self.dimages), len(self.images))
215 74ec726f John Giannelos
216 5a140b23 Vangelis Koukis
    def test_003_same_image_names(self):
217 5a140b23 Vangelis Koukis
        """Test detailed and simple image list contain same names"""
218 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.images))
219 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dimages))
220 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
221 5a140b23 Vangelis Koukis
222 5a140b23 Vangelis Koukis
    def test_004_unique_image_names(self):
223 946da8b6 John Giannelos
        """Test system images have unique names"""
224 946da8b6 John Giannelos
        sys_images = filter(lambda x: x['owner'] == PLANKTON_USER,
225 946da8b6 John Giannelos
                            self.dimages)
226 946da8b6 John Giannelos
        names = sorted(map(lambda x: x["name"], sys_images))
227 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
228 5a140b23 Vangelis Koukis
229 5a140b23 Vangelis Koukis
    def test_005_image_metadata(self):
230 5a140b23 Vangelis Koukis
        """Test every image has specific metadata defined"""
231 2e3b7dc8 John Giannelos
        keys = frozenset(["osfamily", "root_partition"])
232 846980fe John Giannelos
        details = self.client.list_images(detail=True)
233 846980fe John Giannelos
        for i in details:
234 5a140b23 Vangelis Koukis
            self.assertTrue(keys.issubset(i["metadata"]["values"].keys()))
235 5a140b23 Vangelis Koukis
236 5a140b23 Vangelis Koukis
237 5a140b23 Vangelis Koukis
class FlavorsTestCase(unittest.TestCase):
238 5a140b23 Vangelis Koukis
    """Test flavor lists for consistency"""
239 5a140b23 Vangelis Koukis
    @classmethod
240 5a140b23 Vangelis Koukis
    def setUpClass(cls):
241 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of flavors"""
242 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of flavors")
243 1c636ad6 John Giannelos
244 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
245 5a140b23 Vangelis Koukis
        cls.flavors = cls.client.list_flavors()
246 5a140b23 Vangelis Koukis
        cls.dflavors = cls.client.list_flavors(detail=True)
247 66eba2cf John Giannelos
        cls.result_dict = dict()
248 5a140b23 Vangelis Koukis
249 5a140b23 Vangelis Koukis
    def test_001_list_flavors(self):
250 5a140b23 Vangelis Koukis
        """Test flavor list actually returns flavors"""
251 5a140b23 Vangelis Koukis
        self.assertGreater(len(self.flavors), 0)
252 5a140b23 Vangelis Koukis
253 5a140b23 Vangelis Koukis
    def test_002_list_flavors_detailed(self):
254 5a140b23 Vangelis Koukis
        """Test detailed flavor list is the same length as list"""
255 5a140b23 Vangelis Koukis
        self.assertEquals(len(self.dflavors), len(self.flavors))
256 5a140b23 Vangelis Koukis
257 5a140b23 Vangelis Koukis
    def test_003_same_flavor_names(self):
258 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
259 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
260 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dflavors))
261 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
262 5a140b23 Vangelis Koukis
263 5a140b23 Vangelis Koukis
    def test_004_unique_flavor_names(self):
264 5a140b23 Vangelis Koukis
        """Test flavors have unique names"""
265 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.flavors))
266 5a140b23 Vangelis Koukis
        self.assertEqual(sorted(list(set(names))), names)
267 5a140b23 Vangelis Koukis
268 5a140b23 Vangelis Koukis
    def test_005_well_formed_flavor_names(self):
269 5a140b23 Vangelis Koukis
        """Test flavors have names of the form CxxRyyDzz
270 5a140b23 Vangelis Koukis

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

273 5a140b23 Vangelis Koukis
        """
274 5a140b23 Vangelis Koukis
        for f in self.dflavors:
275 5a140b23 Vangelis Koukis
            self.assertEqual("C%dR%dD%d" % (f["cpu"], f["ram"], f["disk"]),
276 5a140b23 Vangelis Koukis
                             f["name"],
277 5a140b23 Vangelis Koukis
                             "Flavor %s does not match its specs." % f["name"])
278 5a140b23 Vangelis Koukis
279 5a140b23 Vangelis Koukis
280 5a140b23 Vangelis Koukis
class ServersTestCase(unittest.TestCase):
281 5a140b23 Vangelis Koukis
    """Test server lists for consistency"""
282 5a140b23 Vangelis Koukis
    @classmethod
283 5a140b23 Vangelis Koukis
    def setUpClass(cls):
284 5a140b23 Vangelis Koukis
        """Initialize kamaki, get (detailed) list of servers"""
285 5a140b23 Vangelis Koukis
        log.info("Getting simple and detailed list of servers")
286 1c636ad6 John Giannelos
287 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
288 5a140b23 Vangelis Koukis
        cls.servers = cls.client.list_servers()
289 5a140b23 Vangelis Koukis
        cls.dservers = cls.client.list_servers(detail=True)
290 66eba2cf John Giannelos
        cls.result_dict = dict()
291 5a140b23 Vangelis Koukis
292 74ec726f John Giannelos
    # def test_001_list_servers(self):
293 74ec726f John Giannelos
    #     """Test server list actually returns servers"""
294 74ec726f John Giannelos
    #     self.assertGreater(len(self.servers), 0)
295 5a140b23 Vangelis Koukis
296 5a140b23 Vangelis Koukis
    def test_002_list_servers_detailed(self):
297 5a140b23 Vangelis Koukis
        """Test detailed server list is the same length as list"""
298 5a140b23 Vangelis Koukis
        self.assertEqual(len(self.dservers), len(self.servers))
299 5a140b23 Vangelis Koukis
300 5a140b23 Vangelis Koukis
    def test_003_same_server_names(self):
301 5a140b23 Vangelis Koukis
        """Test detailed and simple flavor list contain same names"""
302 5a140b23 Vangelis Koukis
        names = sorted(map(lambda x: x["name"], self.servers))
303 5a140b23 Vangelis Koukis
        dnames = sorted(map(lambda x: x["name"], self.dservers))
304 5a140b23 Vangelis Koukis
        self.assertEqual(names, dnames)
305 5a140b23 Vangelis Koukis
306 5a140b23 Vangelis Koukis
307 5a140b23 Vangelis Koukis
# This class gets replicated into actual TestCases dynamically
308 5a140b23 Vangelis Koukis
class SpawnServerTestCase(unittest.TestCase):
309 5a140b23 Vangelis Koukis
    """Test scenario for server of the specified image"""
310 5a140b23 Vangelis Koukis
311 5a140b23 Vangelis Koukis
    @classmethod
312 5a140b23 Vangelis Koukis
    def setUpClass(cls):
313 5a140b23 Vangelis Koukis
        """Initialize a kamaki instance"""
314 2e3b7dc8 John Giannelos
        log.info("Spawning server for image `%s'" %cls.imagename)
315 567ffb85 John Giannelos
        cls.client = ComputeClient(API, TOKEN)
316 567ffb85 John Giannelos
        cls.cyclades = CycladesClient(API, TOKEN)
317 66eba2cf John Giannelos
        cls.result_dict = dict()
318 5a140b23 Vangelis Koukis
319 5a140b23 Vangelis Koukis
    def _get_ipv4(self, server):
320 bc14ba88 Vangelis Koukis
        """Get the public IPv4 of a server from the detailed server info"""
321 1c636ad6 John Giannelos
322 5a140b23 Vangelis Koukis
        public_addrs = filter(lambda x: x["id"] == "public",
323 5a140b23 Vangelis Koukis
                              server["addresses"]["values"])
324 5a140b23 Vangelis Koukis
        self.assertEqual(len(public_addrs), 1)
325 5a140b23 Vangelis Koukis
        ipv4_addrs = filter(lambda x: x["version"] == 4,
326 5a140b23 Vangelis Koukis
                            public_addrs[0]["values"])
327 5a140b23 Vangelis Koukis
        self.assertEqual(len(ipv4_addrs), 1)
328 5a140b23 Vangelis Koukis
        return ipv4_addrs[0]["addr"]
329 5a140b23 Vangelis Koukis
330 5a140b23 Vangelis Koukis
    def _get_ipv6(self, server):
331 bc14ba88 Vangelis Koukis
        """Get the public IPv6 of a server from the detailed server info"""
332 5a140b23 Vangelis Koukis
        public_addrs = filter(lambda x: x["id"] == "public",
333 5a140b23 Vangelis Koukis
                              server["addresses"]["values"])
334 5a140b23 Vangelis Koukis
        self.assertEqual(len(public_addrs), 1)
335 5a140b23 Vangelis Koukis
        ipv6_addrs = filter(lambda x: x["version"] == 6,
336 5a140b23 Vangelis Koukis
                            public_addrs[0]["values"])
337 5a140b23 Vangelis Koukis
        self.assertEqual(len(ipv6_addrs), 1)
338 5a140b23 Vangelis Koukis
        return ipv6_addrs[0]["addr"]
339 5a140b23 Vangelis Koukis
340 bc14ba88 Vangelis Koukis
    def _connect_loginname(self, os):
341 bc14ba88 Vangelis Koukis
        """Return the login name for connections based on the server OS"""
342 1c636ad6 John Giannelos
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
343 21bbbc9b Vangelis Koukis
            return "user"
344 1c636ad6 John Giannelos
        elif os in ("windows", "windows_alpha1"):
345 21bbbc9b Vangelis Koukis
            return "Administrator"
346 bc14ba88 Vangelis Koukis
        else:
347 21bbbc9b Vangelis Koukis
            return "root"
348 bc14ba88 Vangelis Koukis
349 bc14ba88 Vangelis Koukis
    def _verify_server_status(self, current_status, new_status):
350 bc14ba88 Vangelis Koukis
        """Verify a server has switched to a specified status"""
351 bc14ba88 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
352 21bbbc9b Vangelis Koukis
        if server["status"] not in (current_status, new_status):
353 21bbbc9b Vangelis Koukis
            return None  # Do not raise exception, return so the test fails
354 bc14ba88 Vangelis Koukis
        self.assertEquals(server["status"], new_status)
355 bc14ba88 Vangelis Koukis
356 bc14ba88 Vangelis Koukis
    def _get_connected_tcp_socket(self, family, host, port):
357 bc14ba88 Vangelis Koukis
        """Get a connected socket from the specified family to host:port"""
358 bc14ba88 Vangelis Koukis
        sock = None
359 bc14ba88 Vangelis Koukis
        for res in \
360 bc14ba88 Vangelis Koukis
            socket.getaddrinfo(host, port, family, socket.SOCK_STREAM, 0,
361 bc14ba88 Vangelis Koukis
                               socket.AI_PASSIVE):
362 bc14ba88 Vangelis Koukis
            af, socktype, proto, canonname, sa = res
363 bc14ba88 Vangelis Koukis
            try:
364 bc14ba88 Vangelis Koukis
                sock = socket.socket(af, socktype, proto)
365 bc14ba88 Vangelis Koukis
            except socket.error as msg:
366 bc14ba88 Vangelis Koukis
                sock = None
367 bc14ba88 Vangelis Koukis
                continue
368 bc14ba88 Vangelis Koukis
            try:
369 bc14ba88 Vangelis Koukis
                sock.connect(sa)
370 bc14ba88 Vangelis Koukis
            except socket.error as msg:
371 bc14ba88 Vangelis Koukis
                sock.close()
372 bc14ba88 Vangelis Koukis
                sock = None
373 bc14ba88 Vangelis Koukis
                continue
374 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(sock)
375 bc14ba88 Vangelis Koukis
        return sock
376 bc14ba88 Vangelis Koukis
377 bc14ba88 Vangelis Koukis
    def _ping_once(self, ipv6, ip):
378 bc14ba88 Vangelis Koukis
        """Test server responds to a single IPv4 or IPv6 ping"""
379 bc14ba88 Vangelis Koukis
        cmd = "ping%s -c 2 -w 3 %s" % ("6" if ipv6 else "", ip)
380 bc14ba88 Vangelis Koukis
        ping = subprocess.Popen(cmd, shell=True,
381 bc14ba88 Vangelis Koukis
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
382 bc14ba88 Vangelis Koukis
        (stdout, stderr) = ping.communicate()
383 bc14ba88 Vangelis Koukis
        ret = ping.wait()
384 bc14ba88 Vangelis Koukis
        self.assertEquals(ret, 0)
385 5a140b23 Vangelis Koukis
386 bc14ba88 Vangelis Koukis
    def _get_hostname_over_ssh(self, hostip, username, password):
387 bc14ba88 Vangelis Koukis
        ssh = paramiko.SSHClient()
388 bc14ba88 Vangelis Koukis
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
389 bc14ba88 Vangelis Koukis
        try:
390 bc14ba88 Vangelis Koukis
            ssh.connect(hostip, username=username, password=password)
391 bc14ba88 Vangelis Koukis
        except socket.error:
392 bc14ba88 Vangelis Koukis
            raise AssertionError
393 bc14ba88 Vangelis Koukis
        stdin, stdout, stderr = ssh.exec_command("hostname")
394 bc14ba88 Vangelis Koukis
        lines = stdout.readlines()
395 bc14ba88 Vangelis Koukis
        self.assertEqual(len(lines), 1)
396 4fdd25ab Vangelis Koukis
        return lines[0]
397 bc14ba88 Vangelis Koukis
398 bc14ba88 Vangelis Koukis
    def _try_until_timeout_expires(self, warn_timeout, fail_timeout,
399 bc14ba88 Vangelis Koukis
                                   opmsg, callable, *args, **kwargs):
400 bc14ba88 Vangelis Koukis
        if warn_timeout == fail_timeout:
401 5a140b23 Vangelis Koukis
            warn_timeout = fail_timeout + 1
402 5a140b23 Vangelis Koukis
        warn_tmout = time.time() + warn_timeout
403 5a140b23 Vangelis Koukis
        fail_tmout = time.time() + fail_timeout
404 5a140b23 Vangelis Koukis
        while True:
405 4fdd25ab Vangelis Koukis
            self.assertLess(time.time(), fail_tmout,
406 21bbbc9b Vangelis Koukis
                            "operation `%s' timed out" % opmsg)
407 5a140b23 Vangelis Koukis
            if time.time() > warn_tmout:
408 4fdd25ab Vangelis Koukis
                log.warning("Server %d: `%s' operation `%s' not done yet",
409 4fdd25ab Vangelis Koukis
                            self.serverid, self.servername, opmsg)
410 bc14ba88 Vangelis Koukis
            try:
411 4fdd25ab Vangelis Koukis
                log.info("%s... " % opmsg)
412 bc14ba88 Vangelis Koukis
                return callable(*args, **kwargs)
413 bc14ba88 Vangelis Koukis
            except AssertionError:
414 bc14ba88 Vangelis Koukis
                pass
415 5a140b23 Vangelis Koukis
            time.sleep(self.query_interval)
416 5a140b23 Vangelis Koukis
417 bc14ba88 Vangelis Koukis
    def _insist_on_tcp_connection(self, family, host, port):
418 21bbbc9b Vangelis Koukis
        familystr = {socket.AF_INET: "IPv4", socket.AF_INET6: "IPv6",
419 21bbbc9b Vangelis Koukis
                     socket.AF_UNSPEC: "Unspecified-IPv4/6"}
420 bc14ba88 Vangelis Koukis
        msg = "connect over %s to %s:%s" % \
421 bc14ba88 Vangelis Koukis
              (familystr.get(family, "Unknown"), host, port)
422 bc14ba88 Vangelis Koukis
        sock = self._try_until_timeout_expires(
423 bc14ba88 Vangelis Koukis
                self.action_timeout, self.action_timeout,
424 bc14ba88 Vangelis Koukis
                msg, self._get_connected_tcp_socket,
425 bc14ba88 Vangelis Koukis
                family, host, port)
426 bc14ba88 Vangelis Koukis
        return sock
427 bc14ba88 Vangelis Koukis
428 bc14ba88 Vangelis Koukis
    def _insist_on_status_transition(self, current_status, new_status,
429 bc14ba88 Vangelis Koukis
                                    fail_timeout, warn_timeout=None):
430 4fdd25ab Vangelis Koukis
        msg = "Server %d: `%s', waiting for %s -> %s" % \
431 4fdd25ab Vangelis Koukis
              (self.serverid, self.servername, current_status, new_status)
432 bc14ba88 Vangelis Koukis
        if warn_timeout is None:
433 bc14ba88 Vangelis Koukis
            warn_timeout = fail_timeout
434 bc14ba88 Vangelis Koukis
        self._try_until_timeout_expires(warn_timeout, fail_timeout,
435 bc14ba88 Vangelis Koukis
                                        msg, self._verify_server_status,
436 bc14ba88 Vangelis Koukis
                                        current_status, new_status)
437 21bbbc9b Vangelis Koukis
        # Ensure the status is actually the expected one
438 21bbbc9b Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
439 21bbbc9b Vangelis Koukis
        self.assertEquals(server["status"], new_status)
440 bc14ba88 Vangelis Koukis
441 bc14ba88 Vangelis Koukis
    def _insist_on_ssh_hostname(self, hostip, username, password):
442 4fdd25ab Vangelis Koukis
        msg = "SSH to %s, as %s/%s" % (hostip, username, password)
443 bc14ba88 Vangelis Koukis
        hostname = self._try_until_timeout_expires(
444 bc14ba88 Vangelis Koukis
                self.action_timeout, self.action_timeout,
445 bc14ba88 Vangelis Koukis
                msg, self._get_hostname_over_ssh,
446 bc14ba88 Vangelis Koukis
                hostip, username, password)
447 bc14ba88 Vangelis Koukis
448 bc14ba88 Vangelis Koukis
        # The hostname must be of the form 'prefix-id'
449 bc14ba88 Vangelis Koukis
        self.assertTrue(hostname.endswith("-%d\n" % self.serverid))
450 5a140b23 Vangelis Koukis
451 8252d64f John Giannelos
    def _check_file_through_ssh(self, hostip, username, password,
452 8252d64f John Giannelos
                                remotepath, content):
453 8252d64f John Giannelos
        msg = "Trying file injection through SSH to %s, as %s/%s" % \
454 8252d64f John Giannelos
            (hostip, username, password)
455 f97dce4d John Giannelos
        log.info(msg)
456 77054bf5 John Giannelos
        try:
457 77054bf5 John Giannelos
            ssh = paramiko.SSHClient()
458 77054bf5 John Giannelos
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
459 77054bf5 John Giannelos
            ssh.connect(hostip, username=username, password=password)
460 77054bf5 John Giannelos
        except socket.error:
461 77054bf5 John Giannelos
            raise AssertionError
462 9659e075 John Giannelos
463 2bcfb712 John Giannelos
        transport = paramiko.Transport((hostip, 22))
464 2bcfb712 John Giannelos
        transport.connect(username=username, password=password)
465 2bcfb712 John Giannelos
466 2bcfb712 John Giannelos
        localpath = '/tmp/' + SNF_TEST_PREFIX + 'injection'
467 77054bf5 John Giannelos
        sftp = paramiko.SFTPClient.from_transport(transport)
468 8252d64f John Giannelos
        sftp.get(remotepath, localpath)
469 77054bf5 John Giannelos
        sftp.close()
470 77054bf5 John Giannelos
        transport.close()
471 77054bf5 John Giannelos
472 9659e075 John Giannelos
        f = open(localpath)
473 9659e075 John Giannelos
        remote_content = b64encode(f.read())
474 9659e075 John Giannelos
475 77054bf5 John Giannelos
        # Check if files are the same
476 65462ca9 John Giannelos
        return (remote_content == content)
477 77054bf5 John Giannelos
478 5a140b23 Vangelis Koukis
    def _skipIf(self, condition, msg):
479 5a140b23 Vangelis Koukis
        if condition:
480 5a140b23 Vangelis Koukis
            self.skipTest(msg)
481 5a140b23 Vangelis Koukis
482 5a140b23 Vangelis Koukis
    def test_001_submit_create_server(self):
483 5a140b23 Vangelis Koukis
        """Test submit create server request"""
484 f89d0238 John Giannelos
485 f89d0238 John Giannelos
        log.info("Submit new server request")
486 5a140b23 Vangelis Koukis
        server = self.client.create_server(self.servername, self.flavorid,
487 5a140b23 Vangelis Koukis
                                           self.imageid, self.personality)
488 9659e075 John Giannelos
489 81e8cbf6 John Giannelos
        log.info("Server id: " + str(server["id"]))
490 81e8cbf6 John Giannelos
        log.info("Server password: " + server["adminPass"])
491 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
492 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
493 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
494 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
495 5a140b23 Vangelis Koukis
496 5a140b23 Vangelis Koukis
        # Update class attributes to reflect data on building server
497 5a140b23 Vangelis Koukis
        cls = type(self)
498 5a140b23 Vangelis Koukis
        cls.serverid = server["id"]
499 bc14ba88 Vangelis Koukis
        cls.username = None
500 5a140b23 Vangelis Koukis
        cls.passwd = server["adminPass"]
501 5a140b23 Vangelis Koukis
502 66eba2cf John Giannelos
        self.result_dict["Server ID"] = str(server["id"])
503 66eba2cf John Giannelos
        self.result_dict["Password"] = str(server["adminPass"])
504 66eba2cf John Giannelos
505 5a140b23 Vangelis Koukis
    def test_002a_server_is_building_in_list(self):
506 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in server list"""
507 f89d0238 John Giannelos
        log.info("Server in BUILD state in server list")
508 f89d0238 John Giannelos
509 66eba2cf John Giannelos
        self.result_dict.clear()
510 66eba2cf John Giannelos
511 5a140b23 Vangelis Koukis
        servers = self.client.list_servers(detail=True)
512 5a140b23 Vangelis Koukis
        servers = filter(lambda x: x["name"] == self.servername, servers)
513 5a140b23 Vangelis Koukis
        self.assertEqual(len(servers), 1)
514 5a140b23 Vangelis Koukis
        server = servers[0]
515 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
516 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
517 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
518 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
519 5a140b23 Vangelis Koukis
520 5a140b23 Vangelis Koukis
    def test_002b_server_is_building_in_details(self):
521 5a140b23 Vangelis Koukis
        """Test server is in BUILD state, in details"""
522 f89d0238 John Giannelos
523 f89d0238 John Giannelos
        log.info("Server in BUILD state in details")
524 f89d0238 John Giannelos
525 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
526 5a140b23 Vangelis Koukis
        self.assertEqual(server["name"], self.servername)
527 5a140b23 Vangelis Koukis
        self.assertEqual(server["flavorRef"], self.flavorid)
528 5a140b23 Vangelis Koukis
        self.assertEqual(server["imageRef"], self.imageid)
529 5a140b23 Vangelis Koukis
        self.assertEqual(server["status"], "BUILD")
530 5a140b23 Vangelis Koukis
531 5a140b23 Vangelis Koukis
    def test_002c_set_server_metadata(self):
532 f89d0238 John Giannelos
533 f89d0238 John Giannelos
        log.info("Creating server metadata")
534 f89d0238 John Giannelos
535 5a140b23 Vangelis Koukis
        image = self.client.get_image_details(self.imageid)
536 74193008 John Giannelos
        os = image["metadata"]["values"]["os"]
537 e49bdb7c John Giannelos
        users = image["metadata"]["values"].get("users", None)
538 c1d11f96 John Giannelos
        self.client.update_server_metadata(self.serverid, OS=os)
539 746540cd John Giannelos
540 e49bdb7c John Giannelos
        userlist = users.split()
541 81e8cbf6 John Giannelos
542 bc14ba88 Vangelis Koukis
        # Determine the username to use for future connections
543 bc14ba88 Vangelis Koukis
        # to this host
544 bc14ba88 Vangelis Koukis
        cls = type(self)
545 81e8cbf6 John Giannelos
546 81e8cbf6 John Giannelos
        if "root" in userlist:
547 81e8cbf6 John Giannelos
            cls.username = "root"
548 81e8cbf6 John Giannelos
        elif users == None:
549 bc14ba88 Vangelis Koukis
            cls.username = self._connect_loginname(os)
550 81e8cbf6 John Giannelos
        else:
551 81e8cbf6 John Giannelos
            cls.username = choice(userlist)
552 81e8cbf6 John Giannelos
553 bc14ba88 Vangelis Koukis
        self.assertIsNotNone(cls.username)
554 5a140b23 Vangelis Koukis
555 5a140b23 Vangelis Koukis
    def test_002d_verify_server_metadata(self):
556 5a140b23 Vangelis Koukis
        """Test server metadata keys are set based on image metadata"""
557 f89d0238 John Giannelos
558 f89d0238 John Giannelos
        log.info("Verifying image metadata")
559 f89d0238 John Giannelos
560 5a140b23 Vangelis Koukis
        servermeta = self.client.get_server_metadata(self.serverid)
561 5a140b23 Vangelis Koukis
        imagemeta = self.client.get_image_metadata(self.imageid)
562 81e8cbf6 John Giannelos
563 99d41650 John Giannelos
        self.assertEqual(servermeta["OS"], imagemeta["os"])
564 5a140b23 Vangelis Koukis
565 5a140b23 Vangelis Koukis
    def test_003_server_becomes_active(self):
566 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE"""
567 f89d0238 John Giannelos
568 f89d0238 John Giannelos
        log.info("Waiting for server to become ACTIVE")
569 f89d0238 John Giannelos
570 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("BUILD", "ACTIVE",
571 5a140b23 Vangelis Koukis
                                         self.build_fail, self.build_warning)
572 5a140b23 Vangelis Koukis
573 65462ca9 John Giannelos
    def test_003a_get_server_oob_console(self):
574 65462ca9 John Giannelos
        """Test getting OOB server console over VNC
575 bc14ba88 Vangelis Koukis

576 65462ca9 John Giannelos
        Implementation of RFB protocol follows
577 65462ca9 John Giannelos
        http://www.realvnc.com/docs/rfbproto.pdf.
578 bc14ba88 Vangelis Koukis

579 65462ca9 John Giannelos
        """
580 65462ca9 John Giannelos
        console = self.cyclades.get_server_console(self.serverid)
581 65462ca9 John Giannelos
        self.assertEquals(console['type'], "vnc")
582 aa388d48 John Giannelos
        sock = self._insist_on_tcp_connection(socket.AF_INET,
583 65462ca9 John Giannelos
                                        console["host"], console["port"])
584 65462ca9 John Giannelos
585 65462ca9 John Giannelos
        # Step 1. ProtocolVersion message (par. 6.1.1)
586 65462ca9 John Giannelos
        version = sock.recv(1024)
587 65462ca9 John Giannelos
        self.assertEquals(version, 'RFB 003.008\n')
588 65462ca9 John Giannelos
        sock.send(version)
589 65462ca9 John Giannelos
590 65462ca9 John Giannelos
        # Step 2. Security (par 6.1.2): Only VNC Authentication supported
591 65462ca9 John Giannelos
        sec = sock.recv(1024)
592 65462ca9 John Giannelos
        self.assertEquals(list(sec), ['\x01', '\x02'])
593 65462ca9 John Giannelos
594 65462ca9 John Giannelos
        # Step 3. Request VNC Authentication (par 6.1.2)
595 65462ca9 John Giannelos
        sock.send('\x02')
596 65462ca9 John Giannelos
597 65462ca9 John Giannelos
        # Step 4. Receive Challenge (par 6.2.2)
598 65462ca9 John Giannelos
        challenge = sock.recv(1024)
599 65462ca9 John Giannelos
        self.assertEquals(len(challenge), 16)
600 65462ca9 John Giannelos
601 65462ca9 John Giannelos
        # Step 5. DES-Encrypt challenge, use password as key (par 6.2.2)
602 65462ca9 John Giannelos
        response = d3des_generate_response(
603 65462ca9 John Giannelos
            (console["password"] + '\0' * 8)[:8], challenge)
604 65462ca9 John Giannelos
        sock.send(response)
605 65462ca9 John Giannelos
606 65462ca9 John Giannelos
        # Step 6. SecurityResult (par 6.1.3)
607 65462ca9 John Giannelos
        result = sock.recv(4)
608 65462ca9 John Giannelos
        self.assertEquals(list(result), ['\x00', '\x00', '\x00', '\x00'])
609 65462ca9 John Giannelos
        sock.close()
610 8252d64f John Giannelos
611 5a140b23 Vangelis Koukis
    def test_004_server_has_ipv4(self):
612 5a140b23 Vangelis Koukis
        """Test active server has a valid IPv4 address"""
613 f89d0238 John Giannelos
614 81e8cbf6 John Giannelos
        log.info("Validate server's IPv4")
615 f89d0238 John Giannelos
616 66eba2cf John Giannelos
617 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
618 5a140b23 Vangelis Koukis
        ipv4 = self._get_ipv4(server)
619 66eba2cf John Giannelos
620 66eba2cf John Giannelos
        self.result_dict.clear()
621 66eba2cf John Giannelos
        self.result_dict["IPv4"] = str(ipv4)
622 66eba2cf John Giannelos
623 5a140b23 Vangelis Koukis
        self.assertEquals(IP(ipv4).version(), 4)
624 5a140b23 Vangelis Koukis
625 65462ca9 John Giannelos
    def test_005_server_has_ipv6(self):
626 65462ca9 John Giannelos
        """Test active server has a valid IPv6 address"""
627 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
628 f89d0238 John Giannelos
629 81e8cbf6 John Giannelos
        log.info("Validate server's IPv6")
630 f89d0238 John Giannelos
631 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
632 65462ca9 John Giannelos
        ipv6 = self._get_ipv6(server)
633 66eba2cf John Giannelos
634 66eba2cf John Giannelos
        self.result_dict.clear()
635 66eba2cf John Giannelos
        self.result_dict["IPv6"] = str(ipv6)
636 66eba2cf John Giannelos
637 65462ca9 John Giannelos
        self.assertEquals(IP(ipv6).version(), 6)
638 5a140b23 Vangelis Koukis
639 5a140b23 Vangelis Koukis
    def test_006_server_responds_to_ping_IPv4(self):
640 5a140b23 Vangelis Koukis
        """Test server responds to ping on IPv4 address"""
641 f89d0238 John Giannelos
642 f89d0238 John Giannelos
        log.info("Testing if server responds to pings in IPv4")
643 66eba2cf John Giannelos
        self.result_dict.clear()
644 f89d0238 John Giannelos
645 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
646 bc14ba88 Vangelis Koukis
        ip = self._get_ipv4(server)
647 bc14ba88 Vangelis Koukis
        self._try_until_timeout_expires(self.action_timeout,
648 bc14ba88 Vangelis Koukis
                                        self.action_timeout,
649 4fdd25ab Vangelis Koukis
                                        "PING IPv4 to %s" % ip,
650 4fdd25ab Vangelis Koukis
                                        self._ping_once,
651 bc14ba88 Vangelis Koukis
                                        False, ip)
652 5a140b23 Vangelis Koukis
653 65462ca9 John Giannelos
    def test_007_server_responds_to_ping_IPv6(self):
654 65462ca9 John Giannelos
        """Test server responds to ping on IPv6 address"""
655 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
656 f89d0238 John Giannelos
        log.info("Testing if server responds to pings in IPv6")
657 f89d0238 John Giannelos
658 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
659 65462ca9 John Giannelos
        ip = self._get_ipv6(server)
660 65462ca9 John Giannelos
        self._try_until_timeout_expires(self.action_timeout,
661 65462ca9 John Giannelos
                                        self.action_timeout,
662 65462ca9 John Giannelos
                                        "PING IPv6 to %s" % ip,
663 65462ca9 John Giannelos
                                        self._ping_once,
664 65462ca9 John Giannelos
                                        True, ip)
665 5a140b23 Vangelis Koukis
666 5a140b23 Vangelis Koukis
    def test_008_submit_shutdown_request(self):
667 5a140b23 Vangelis Koukis
        """Test submit request to shutdown server"""
668 f89d0238 John Giannelos
669 f89d0238 John Giannelos
        log.info("Shutting down server")
670 f89d0238 John Giannelos
671 74193008 John Giannelos
        self.cyclades.shutdown_server(self.serverid)
672 5a140b23 Vangelis Koukis
673 5a140b23 Vangelis Koukis
    def test_009_server_becomes_stopped(self):
674 5a140b23 Vangelis Koukis
        """Test server becomes STOPPED"""
675 f89d0238 John Giannelos
676 f89d0238 John Giannelos
        log.info("Waiting until server becomes STOPPED")
677 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("ACTIVE", "STOPPED",
678 bc14ba88 Vangelis Koukis
                                         self.action_timeout,
679 5a140b23 Vangelis Koukis
                                         self.action_timeout)
680 5a140b23 Vangelis Koukis
681 5a140b23 Vangelis Koukis
    def test_010_submit_start_request(self):
682 5a140b23 Vangelis Koukis
        """Test submit start server request"""
683 f89d0238 John Giannelos
684 f89d0238 John Giannelos
        log.info("Starting server")
685 f89d0238 John Giannelos
686 74193008 John Giannelos
        self.cyclades.start_server(self.serverid)
687 5a140b23 Vangelis Koukis
688 5a140b23 Vangelis Koukis
    def test_011_server_becomes_active(self):
689 5a140b23 Vangelis Koukis
        """Test server becomes ACTIVE again"""
690 f89d0238 John Giannelos
691 f89d0238 John Giannelos
        log.info("Waiting until server becomes ACTIVE")
692 bc14ba88 Vangelis Koukis
        self._insist_on_status_transition("STOPPED", "ACTIVE",
693 bc14ba88 Vangelis Koukis
                                         self.action_timeout,
694 5a140b23 Vangelis Koukis
                                         self.action_timeout)
695 5a140b23 Vangelis Koukis
696 5a140b23 Vangelis Koukis
    def test_011a_server_responds_to_ping_IPv4(self):
697 5a140b23 Vangelis Koukis
        """Test server OS is actually up and running again"""
698 f89d0238 John Giannelos
699 f89d0238 John Giannelos
        log.info("Testing if server is actually up and running")
700 f89d0238 John Giannelos
701 5a140b23 Vangelis Koukis
        self.test_006_server_responds_to_ping_IPv4()
702 5a140b23 Vangelis Koukis
703 5a140b23 Vangelis Koukis
    def test_012_ssh_to_server_IPv4(self):
704 5a140b23 Vangelis Koukis
        """Test SSH to server public IPv4 works, verify hostname"""
705 f89d0238 John Giannelos
706 bc14ba88 Vangelis Koukis
        self._skipIf(self.is_windows, "only valid for Linux servers")
707 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
708 bc14ba88 Vangelis Koukis
        self._insist_on_ssh_hostname(self._get_ipv4(server),
709 bc14ba88 Vangelis Koukis
                                     self.username, self.passwd)
710 5a140b23 Vangelis Koukis
711 65462ca9 John Giannelos
    def test_013_ssh_to_server_IPv6(self):
712 65462ca9 John Giannelos
        """Test SSH to server public IPv6 works, verify hostname"""
713 65462ca9 John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
714 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
715 946da8b6 John Giannelos
716 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
717 65462ca9 John Giannelos
        self._insist_on_ssh_hostname(self._get_ipv6(server),
718 65462ca9 John Giannelos
                                     self.username, self.passwd)
719 5a140b23 Vangelis Koukis
720 5a140b23 Vangelis Koukis
    def test_014_rdp_to_server_IPv4(self):
721 5a140b23 Vangelis Koukis
        "Test RDP connection to server public IPv4 works"""
722 bc14ba88 Vangelis Koukis
        self._skipIf(not self.is_windows, "only valid for Windows servers")
723 5a140b23 Vangelis Koukis
        server = self.client.get_server_details(self.serverid)
724 5a140b23 Vangelis Koukis
        ipv4 = self._get_ipv4(server)
725 bc14ba88 Vangelis Koukis
        sock = _insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
726 5a140b23 Vangelis Koukis
727 5a140b23 Vangelis Koukis
        # No actual RDP processing done. We assume the RDP server is there
728 5a140b23 Vangelis Koukis
        # if the connection to the RDP port is successful.
729 cb1fa17c Vangelis Koukis
        # FIXME: Use rdesktop, analyze exit code? see manpage [costasd]
730 5a140b23 Vangelis Koukis
        sock.close()
731 5a140b23 Vangelis Koukis
732 65462ca9 John Giannelos
    def test_015_rdp_to_server_IPv6(self):
733 65462ca9 John Giannelos
        "Test RDP connection to server public IPv6 works"""
734 65462ca9 John Giannelos
        self._skipIf(not self.is_windows, "only valid for Windows servers")
735 946da8b6 John Giannelos
        self._skipIf(NO_IPV6, "--no-ipv6 flag enabled")
736 946da8b6 John Giannelos
737 65462ca9 John Giannelos
        server = self.client.get_server_details(self.serverid)
738 65462ca9 John Giannelos
        ipv6 = self._get_ipv6(server)
739 65462ca9 John Giannelos
        sock = _get_tcp_connection(socket.AF_INET6, ipv6, 3389)
740 5a140b23 Vangelis Koukis
741 65462ca9 John Giannelos
        # No actual RDP processing done. We assume the RDP server is there
742 65462ca9 John Giannelos
        # if the connection to the RDP port is successful.
743 65462ca9 John Giannelos
        sock.close()
744 5a140b23 Vangelis Koukis
745 5a140b23 Vangelis Koukis
    def test_016_personality_is_enforced(self):
746 5a140b23 Vangelis Koukis
        """Test file injection for personality enforcement"""
747 21dcb666 John Giannelos
        self._skipIf(self.is_windows, "only implemented for Linux servers")
748 21dcb666 John Giannelos
        self._skipIf(self.personality == None, "No personality file selected")
749 f89d0238 John Giannelos
750 f89d0238 John Giannelos
        log.info("Trying to inject file for personality enforcement")
751 f89d0238 John Giannelos
752 77054bf5 John Giannelos
        server = self.client.get_server_details(self.serverid)
753 77054bf5 John Giannelos
754 9659e075 John Giannelos
        for inj_file in self.personality:
755 8252d64f John Giannelos
            equal_files = self._check_file_through_ssh(self._get_ipv4(server),
756 8252d64f John Giannelos
                                                       inj_file['owner'],
757 8252d64f John Giannelos
                                                       self.passwd,
758 8252d64f John Giannelos
                                                       inj_file['path'],
759 8252d64f John Giannelos
                                                       inj_file['contents'])
760 9659e075 John Giannelos
            self.assertTrue(equal_files)
761 8252d64f John Giannelos
762 4fdd25ab Vangelis Koukis
    def test_017_submit_delete_request(self):
763 4fdd25ab Vangelis Koukis
        """Test submit request to delete server"""
764 f89d0238 John Giannelos
765 f89d0238 John Giannelos
        log.info("Deleting server")
766 f89d0238 John Giannelos
767 4fdd25ab Vangelis Koukis
        self.client.delete_server(self.serverid)
768 4fdd25ab Vangelis Koukis
769 4fdd25ab Vangelis Koukis
    def test_018_server_becomes_deleted(self):
770 4fdd25ab Vangelis Koukis
        """Test server becomes DELETED"""
771 f89d0238 John Giannelos
772 f89d0238 John Giannelos
        log.info("Testing if server becomes DELETED")
773 f89d0238 John Giannelos
774 4fdd25ab Vangelis Koukis
        self._insist_on_status_transition("ACTIVE", "DELETED",
775 4fdd25ab Vangelis Koukis
                                         self.action_timeout,
776 4fdd25ab Vangelis Koukis
                                         self.action_timeout)
777 4fdd25ab Vangelis Koukis
778 4fdd25ab Vangelis Koukis
    def test_019_server_no_longer_in_server_list(self):
779 4fdd25ab Vangelis Koukis
        """Test server is no longer in server list"""
780 f89d0238 John Giannelos
781 f89d0238 John Giannelos
        log.info("Test if server is no longer listed")
782 f89d0238 John Giannelos
783 4fdd25ab Vangelis Koukis
        servers = self.client.list_servers()
784 21bbbc9b Vangelis Koukis
        self.assertNotIn(self.serverid, [s["id"] for s in servers])
785 21bbbc9b Vangelis Koukis
786 21bbbc9b Vangelis Koukis
787 9e4682b5 John Giannelos
class NetworkTestCase(unittest.TestCase):
788 e94a9d8c John Giannelos
    """ Testing networking in cyclades """
789 8252d64f John Giannelos
790 9e4682b5 John Giannelos
    @classmethod
791 e94a9d8c John Giannelos
    def setUpClass(cls):
792 e94a9d8c John Giannelos
        "Initialize kamaki, get list of current networks"
793 567ffb85 John Giannelos
794 567ffb85 John Giannelos
        cls.client = CycladesClient(API, TOKEN)
795 567ffb85 John Giannelos
        cls.compute = ComputeClient(API, TOKEN)
796 9e4682b5 John Giannelos
797 8252d64f John Giannelos
        cls.servername = "%s%s for %s" % (SNF_TEST_PREFIX,
798 8252d64f John Giannelos
                                          TEST_RUN_ID,
799 8252d64f John Giannelos
                                          cls.imagename)
800 91de9b55 John Giannelos
801 91de9b55 John Giannelos
        #Dictionary initialization for the vms credentials
802 91de9b55 John Giannelos
        cls.serverid = dict()
803 91de9b55 John Giannelos
        cls.username = dict()
804 91de9b55 John Giannelos
        cls.password = dict()
805 846980fe John Giannelos
        cls.is_windows = cls.imagename.lower().find("windows") >= 0
806 e49bdb7c John Giannelos
807 66eba2cf John Giannelos
        cls.result_dict = dict()
808 66eba2cf John Giannelos
809 e49bdb7c John Giannelos
    def _skipIf(self, condition, msg):
810 e49bdb7c John Giannelos
        if condition:
811 e49bdb7c John Giannelos
            self.skipTest(msg)
812 91de9b55 John Giannelos
813 1b40b5e3 John Giannelos
    def _get_ipv4(self, server):
814 1b40b5e3 John Giannelos
        """Get the public IPv4 of a server from the detailed server info"""
815 1b40b5e3 John Giannelos
816 1b40b5e3 John Giannelos
        public_addrs = filter(lambda x: x["id"] == "public",
817 1b40b5e3 John Giannelos
                              server["addresses"]["values"])
818 1b40b5e3 John Giannelos
        self.assertEqual(len(public_addrs), 1)
819 1b40b5e3 John Giannelos
        ipv4_addrs = filter(lambda x: x["version"] == 4,
820 1b40b5e3 John Giannelos
                            public_addrs[0]["values"])
821 1b40b5e3 John Giannelos
        self.assertEqual(len(ipv4_addrs), 1)
822 1b40b5e3 John Giannelos
        return ipv4_addrs[0]["addr"]
823 8252d64f John Giannelos
824 1b40b5e3 John Giannelos
    def _connect_loginname(self, os):
825 1b40b5e3 John Giannelos
        """Return the login name for connections based on the server OS"""
826 1b40b5e3 John Giannelos
        if os in ("Ubuntu", "Kubuntu", "Fedora"):
827 1b40b5e3 John Giannelos
            return "user"
828 1b40b5e3 John Giannelos
        elif os in ("windows", "windows_alpha1"):
829 1b40b5e3 John Giannelos
            return "Administrator"
830 1b40b5e3 John Giannelos
        else:
831 1b40b5e3 John Giannelos
            return "root"
832 1b40b5e3 John Giannelos
833 88736f65 John Giannelos
    def _ping_once(self, ip):
834 8252d64f John Giannelos
835 88736f65 John Giannelos
        """Test server responds to a single IPv4 or IPv6 ping"""
836 88736f65 John Giannelos
        cmd = "ping -c 2 -w 3 %s" % (ip)
837 88736f65 John Giannelos
        ping = subprocess.Popen(cmd, shell=True,
838 88736f65 John Giannelos
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
839 88736f65 John Giannelos
        (stdout, stderr) = ping.communicate()
840 88736f65 John Giannelos
        ret = ping.wait()
841 8252d64f John Giannelos
842 88736f65 John Giannelos
        return (ret == 0)
843 88736f65 John Giannelos
844 740a5649 John Giannelos
    def test_00001a_submit_create_server_A(self):
845 91de9b55 John Giannelos
        """Test submit create server request"""
846 f89d0238 John Giannelos
847 f89d0238 John Giannelos
        log.info("Creating test server A")
848 f89d0238 John Giannelos
849 91de9b55 John Giannelos
        serverA = self.client.create_server(self.servername, self.flavorid,
850 ae139e8a John Giannelos
                                            self.imageid, personality=None)
851 91de9b55 John Giannelos
852 c54e3d4c John Giannelos
        self.assertEqual(serverA["name"], self.servername)
853 c54e3d4c John Giannelos
        self.assertEqual(serverA["flavorRef"], self.flavorid)
854 c54e3d4c John Giannelos
        self.assertEqual(serverA["imageRef"], self.imageid)
855 c54e3d4c John Giannelos
        self.assertEqual(serverA["status"], "BUILD")
856 91de9b55 John Giannelos
857 91de9b55 John Giannelos
        # Update class attributes to reflect data on building server
858 08748d73 John Giannelos
        self.serverid['A'] = serverA["id"]
859 08748d73 John Giannelos
        self.username['A'] = None
860 08748d73 John Giannelos
        self.password['A'] = serverA["adminPass"]
861 91de9b55 John Giannelos
862 81e8cbf6 John Giannelos
        log.info("Server A id:" + str(serverA["id"]))
863 81e8cbf6 John Giannelos
        log.info("Server password " + (self.password['A']))
864 8252d64f John Giannelos
865 66eba2cf John Giannelos
        self.result_dict["Server A ID"] = str(serverA["id"])
866 66eba2cf John Giannelos
        self.result_dict["Server A password"] = serverA["adminPass"]
867 66eba2cf John Giannelos
        
868 740a5649 John Giannelos
    def test_00001b_serverA_becomes_active(self):
869 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
870 8252d64f John Giannelos
871 f89d0238 John Giannelos
        log.info("Waiting until test server A becomes ACTIVE")
872 66eba2cf John Giannelos
        self.result_dict.clear()
873 91de9b55 John Giannelos
874 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
875 91de9b55 John Giannelos
        while True:
876 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
877 91de9b55 John Giannelos
            status = d['status']
878 91de9b55 John Giannelos
            if status == 'ACTIVE':
879 91de9b55 John Giannelos
                active = True
880 91de9b55 John Giannelos
                break
881 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
882 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
883 91de9b55 John Giannelos
            else:
884 91de9b55 John Giannelos
                time.sleep(self.query_interval)
885 91de9b55 John Giannelos
886 91de9b55 John Giannelos
        self.assertTrue(active)
887 91de9b55 John Giannelos
888 740a5649 John Giannelos
    def test_00002a_submit_create_server_B(self):
889 fade8dab John Giannelos
        """Test submit create server request"""
890 8252d64f John Giannelos
891 f89d0238 John Giannelos
        log.info("Creating test server B")
892 66eba2cf John Giannelos
        
893 fade8dab John Giannelos
        serverB = self.client.create_server(self.servername, self.flavorid,
894 ae139e8a John Giannelos
                                            self.imageid, personality=None)
895 ae139e8a John Giannelos
896 fade8dab John Giannelos
        self.assertEqual(serverB["name"], self.servername)
897 fade8dab John Giannelos
        self.assertEqual(serverB["flavorRef"], self.flavorid)
898 fade8dab John Giannelos
        self.assertEqual(serverB["imageRef"], self.imageid)
899 fade8dab John Giannelos
        self.assertEqual(serverB["status"], "BUILD")
900 fade8dab John Giannelos
901 fade8dab John Giannelos
        # Update class attributes to reflect data on building server
902 fade8dab John Giannelos
        self.serverid['B'] = serverB["id"]
903 fade8dab John Giannelos
        self.username['B'] = None
904 fade8dab John Giannelos
        self.password['B'] = serverB["adminPass"]
905 fade8dab John Giannelos
906 81e8cbf6 John Giannelos
        log.info("Server B id: " + str(serverB["id"]))
907 81e8cbf6 John Giannelos
        log.info("Password " + (self.password['B']))
908 ae139e8a John Giannelos
909 66eba2cf John Giannelos
        self.result_dict.clear()
910 66eba2cf John Giannelos
        self.result_dict["Server B ID"] = str(serverB["id"])
911 66eba2cf John Giannelos
        self.result_dict["Server B password"] = serverB["adminPass"]
912 66eba2cf John Giannelos
913 740a5649 John Giannelos
    def test_00002b_serverB_becomes_active(self):
914 91de9b55 John Giannelos
        """Test server becomes ACTIVE"""
915 91de9b55 John Giannelos
916 f89d0238 John Giannelos
        log.info("Waiting until test server B becomes ACTIVE")
917 66eba2cf John Giannelos
        self.result_dict.clear()
918 f89d0238 John Giannelos
919 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
920 91de9b55 John Giannelos
        while True:
921 91de9b55 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
922 91de9b55 John Giannelos
            status = d['status']
923 91de9b55 John Giannelos
            if status == 'ACTIVE':
924 91de9b55 John Giannelos
                active = True
925 91de9b55 John Giannelos
                break
926 91de9b55 John Giannelos
            elif time.time() > fail_tmout:
927 91de9b55 John Giannelos
                self.assertLess(time.time(), fail_tmout)
928 91de9b55 John Giannelos
            else:
929 91de9b55 John Giannelos
                time.sleep(self.query_interval)
930 91de9b55 John Giannelos
931 91de9b55 John Giannelos
        self.assertTrue(active)
932 567ffb85 John Giannelos
933 9e4682b5 John Giannelos
    def test_001_create_network(self):
934 e94a9d8c John Giannelos
        """Test submit create network request"""
935 f89d0238 John Giannelos
936 f89d0238 John Giannelos
        log.info("Submit new network request")
937 66eba2cf John Giannelos
        self.result_dict.clear()
938 66eba2cf John Giannelos
                
939 2bcfb712 John Giannelos
        name = SNF_TEST_PREFIX + TEST_RUN_ID
940 9e4682b5 John Giannelos
        previous_num = len(self.client.list_networks())
941 2bcfb712 John Giannelos
        network = self.client.create_network(name)
942 8252d64f John Giannelos
943 9e4682b5 John Giannelos
        #Test if right name is assigned
944 e94a9d8c John Giannelos
        self.assertEqual(network['name'], name)
945 8252d64f John Giannelos
946 9e4682b5 John Giannelos
        # Update class attributes
947 e94a9d8c John Giannelos
        cls = type(self)
948 e94a9d8c John Giannelos
        cls.networkid = network['id']
949 9e4682b5 John Giannelos
        networks = self.client.list_networks()
950 9e4682b5 John Giannelos
951 9e4682b5 John Giannelos
        #Test if new network is created
952 9e4682b5 John Giannelos
        self.assertTrue(len(networks) > previous_num)
953 8252d64f John Giannelos
954 66eba2cf John Giannelos
        self.result_dict["Private network ID"] = str(network['id'])
955 66eba2cf John Giannelos
956 9e4682b5 John Giannelos
    def test_002_connect_to_network(self):
957 4573ea07 John Giannelos
        """Test connect VMs to network"""
958 9e4682b5 John Giannelos
959 f89d0238 John Giannelos
        log.info("Connect VMs to private network")
960 66eba2cf John Giannelos
        self.result_dict.clear()
961 f89d0238 John Giannelos
962 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['A'], self.networkid)
963 91de9b55 John Giannelos
        self.client.connect_server(self.serverid['B'], self.networkid)
964 8252d64f John Giannelos
965 65462ca9 John Giannelos
        #Insist on connecting until action timeout
966 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
967 9e4682b5 John Giannelos
968 65462ca9 John Giannelos
        while True:
969 de2461ec John Giannelos
            connected = (self.client.get_network_details(self.networkid))
970 65462ca9 John Giannelos
            connections = connected['servers']['values']
971 8252d64f John Giannelos
            if (self.serverid['A'] in connections) \
972 8252d64f John Giannelos
                    and (self.serverid['B'] in connections):
973 65462ca9 John Giannelos
                conn_exists = True
974 de2461ec John Giannelos
                break
975 de2461ec John Giannelos
            elif time.time() > fail_tmout:
976 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
977 65462ca9 John Giannelos
            else:
978 65462ca9 John Giannelos
                time.sleep(self.query_interval)
979 65462ca9 John Giannelos
980 65462ca9 John Giannelos
        self.assertTrue(conn_exists)
981 9e4682b5 John Giannelos
982 88736f65 John Giannelos
    def test_002a_reboot(self):
983 f89d0238 John Giannelos
        """Rebooting server A"""
984 f89d0238 John Giannelos
985 f89d0238 John Giannelos
        log.info("Rebooting server A")
986 f89d0238 John Giannelos
987 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['A'])
988 8252d64f John Giannelos
989 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
990 4573ea07 John Giannelos
        while True:
991 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
992 4573ea07 John Giannelos
            status = d['status']
993 81e8cbf6 John Giannelos
            if status == 'STOPPED':
994 81e8cbf6 John Giannelos
                break
995 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
996 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
997 81e8cbf6 John Giannelos
            else:
998 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
999 81e8cbf6 John Giannelos
1000 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['A'])
1001 81e8cbf6 John Giannelos
1002 81e8cbf6 John Giannelos
        while True:
1003 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['A'])
1004 81e8cbf6 John Giannelos
            status = d['status']
1005 4573ea07 John Giannelos
            if status == 'ACTIVE':
1006 4573ea07 John Giannelos
                active = True
1007 4573ea07 John Giannelos
                break
1008 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
1009 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1010 4573ea07 John Giannelos
            else:
1011 4573ea07 John Giannelos
                time.sleep(self.query_interval)
1012 8252d64f John Giannelos
1013 4573ea07 John Giannelos
        self.assertTrue(active)
1014 88736f65 John Giannelos
1015 4573ea07 John Giannelos
    def test_002b_ping_server_A(self):
1016 9b013c3a John Giannelos
        "Test if server A responds to IPv4 pings"
1017 4573ea07 John Giannelos
1018 9b013c3a John Giannelos
        log.info("Testing if server A responds to IPv4 pings ")
1019 66eba2cf John Giannelos
        self.result_dict.clear()
1020 f89d0238 John Giannelos
1021 88736f65 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1022 88736f65 John Giannelos
        ip = self._get_ipv4(server)
1023 8252d64f John Giannelos
1024 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1025 8252d64f John Giannelos
1026 88736f65 John Giannelos
        s = False
1027 66eba2cf John Giannelos
        
1028 66eba2cf John Giannelos
        self.result_dict["Server A public IP"] = str(ip)
1029 88736f65 John Giannelos
1030 88736f65 John Giannelos
        while True:
1031 88736f65 John Giannelos
1032 88736f65 John Giannelos
            if self._ping_once(ip):
1033 88736f65 John Giannelos
                s = True
1034 88736f65 John Giannelos
                break
1035 88736f65 John Giannelos
1036 88736f65 John Giannelos
            elif time.time() > fail_tmout:
1037 88736f65 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1038 88736f65 John Giannelos
1039 88736f65 John Giannelos
            else:
1040 88736f65 John Giannelos
                time.sleep(self.query_interval)
1041 88736f65 John Giannelos
1042 88736f65 John Giannelos
        self.assertTrue(s)
1043 4573ea07 John Giannelos
1044 4573ea07 John Giannelos
    def test_002c_reboot(self):
1045 f89d0238 John Giannelos
        """Reboot server B"""
1046 f89d0238 John Giannelos
1047 f89d0238 John Giannelos
        log.info("Rebooting server B")
1048 66eba2cf John Giannelos
        self.result_dict.clear()
1049 f89d0238 John Giannelos
1050 8252d64f John Giannelos
        self.client.shutdown_server(self.serverid['B'])
1051 8252d64f John Giannelos
1052 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1053 4573ea07 John Giannelos
        while True:
1054 4573ea07 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
1055 4573ea07 John Giannelos
            status = d['status']
1056 81e8cbf6 John Giannelos
            if status == 'STOPPED':
1057 81e8cbf6 John Giannelos
                break
1058 81e8cbf6 John Giannelos
            elif time.time() > fail_tmout:
1059 81e8cbf6 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1060 81e8cbf6 John Giannelos
            else:
1061 81e8cbf6 John Giannelos
                time.sleep(self.query_interval)
1062 81e8cbf6 John Giannelos
1063 81e8cbf6 John Giannelos
        self.client.start_server(self.serverid['B'])
1064 81e8cbf6 John Giannelos
1065 81e8cbf6 John Giannelos
        while True:
1066 81e8cbf6 John Giannelos
            d = self.client.get_server_details(self.serverid['B'])
1067 81e8cbf6 John Giannelos
            status = d['status']
1068 4573ea07 John Giannelos
            if status == 'ACTIVE':
1069 4573ea07 John Giannelos
                active = True
1070 4573ea07 John Giannelos
                break
1071 4573ea07 John Giannelos
            elif time.time() > fail_tmout:
1072 4573ea07 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1073 4573ea07 John Giannelos
            else:
1074 4573ea07 John Giannelos
                time.sleep(self.query_interval)
1075 8252d64f John Giannelos
1076 4573ea07 John Giannelos
        self.assertTrue(active)
1077 8252d64f John Giannelos
1078 88736f65 John Giannelos
    def test_002d_ping_server_B(self):
1079 9b013c3a John Giannelos
        """Test if server B responds to IPv4 pings"""
1080 4573ea07 John Giannelos
1081 9b013c3a John Giannelos
        log.info("Testing if server B responds to IPv4 pings")
1082 66eba2cf John Giannelos
        self.result_dict.clear()
1083 66eba2cf John Giannelos
        
1084 88736f65 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1085 88736f65 John Giannelos
        ip = self._get_ipv4(server)
1086 8252d64f John Giannelos
1087 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1088 8252d64f John Giannelos
1089 88736f65 John Giannelos
        s = False
1090 88736f65 John Giannelos
1091 66eba2cf John Giannelos
        self.result_dict["Server B public IP"] = str(ip)
1092 66eba2cf John Giannelos
1093 88736f65 John Giannelos
        while True:
1094 88736f65 John Giannelos
            if self._ping_once(ip):
1095 88736f65 John Giannelos
                s = True
1096 88736f65 John Giannelos
                break
1097 88736f65 John Giannelos
1098 88736f65 John Giannelos
            elif time.time() > fail_tmout:
1099 88736f65 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1100 88736f65 John Giannelos
1101 88736f65 John Giannelos
            else:
1102 88736f65 John Giannelos
                time.sleep(self.query_interval)
1103 88736f65 John Giannelos
1104 88736f65 John Giannelos
        self.assertTrue(s)
1105 88736f65 John Giannelos
1106 88736f65 John Giannelos
    def test_003a_setup_interface_A(self):
1107 f89d0238 John Giannelos
        """Set up eth1 for server A"""
1108 f89d0238 John Giannelos
1109 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1110 e49bdb7c John Giannelos
1111 f89d0238 John Giannelos
        log.info("Setting up interface eth1 for server A")
1112 66eba2cf John Giannelos
        self.result_dict.clear()
1113 ae139e8a John Giannelos
1114 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1115 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1116 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1117 8252d64f John Giannelos
1118 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1119 d5cc50b3 John Giannelos
        userlist = users.split()
1120 d5cc50b3 John Giannelos
1121 d5cc50b3 John Giannelos
        if "root" in userlist:
1122 d5cc50b3 John Giannelos
            loginname = "root"
1123 d5cc50b3 John Giannelos
        elif users == None:
1124 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1125 d5cc50b3 John Giannelos
        else:
1126 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1127 1b40b5e3 John Giannelos
1128 ae139e8a John Giannelos
        hostip = self._get_ipv4(server)
1129 740a5649 John Giannelos
        myPass = self.password['A']
1130 8252d64f John Giannelos
1131 2bcfb712 John Giannelos
        log.info("SSH in server A as %s/%s" % (loginname, myPass))
1132 8252d64f John Giannelos
1133 88736f65 John Giannelos
        res = False
1134 1b40b5e3 John Giannelos
1135 d5cc50b3 John Giannelos
        if loginname != "root":
1136 88736f65 John Giannelos
            with settings(
1137 33ae1493 John Giannelos
                hide('warnings', 'running'),
1138 8252d64f John Giannelos
                warn_only=True,
1139 8252d64f John Giannelos
                host_string=hostip,
1140 8252d64f John Giannelos
                user=loginname, password=myPass
1141 88736f65 John Giannelos
                ):
1142 88736f65 John Giannelos
1143 8252d64f John Giannelos
                if len(sudo('ifconfig eth1 192.168.0.12')) == 0:
1144 88736f65 John Giannelos
                    res = True
1145 8252d64f John Giannelos
1146 ae139e8a John Giannelos
        else:
1147 ae139e8a John Giannelos
            with settings(
1148 33ae1493 John Giannelos
                hide('warnings', 'running'),
1149 8252d64f John Giannelos
                warn_only=True,
1150 8252d64f John Giannelos
                host_string=hostip,
1151 8252d64f John Giannelos
                user=loginname, password=myPass
1152 ae139e8a John Giannelos
                ):
1153 4573ea07 John Giannelos
1154 33ae1493 John Giannelos
                if len(run('ifconfig eth1 192.168.0.12')) == 0:
1155 ae139e8a John Giannelos
                    res = True
1156 88736f65 John Giannelos
1157 88736f65 John Giannelos
        self.assertTrue(res)
1158 1b40b5e3 John Giannelos
1159 88736f65 John Giannelos
    def test_003b_setup_interface_B(self):
1160 f89d0238 John Giannelos
        """Setup eth1 for server B"""
1161 1b40b5e3 John Giannelos
1162 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1163 e49bdb7c John Giannelos
1164 f89d0238 John Giannelos
        log.info("Setting up interface eth1 for server B")
1165 ae139e8a John Giannelos
1166 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['B'])
1167 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1168 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1169 8252d64f John Giannelos
1170 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1171 d5cc50b3 John Giannelos
        userlist = users.split()
1172 d5cc50b3 John Giannelos
1173 d5cc50b3 John Giannelos
        if "root" in userlist:
1174 d5cc50b3 John Giannelos
            loginname = "root"
1175 d5cc50b3 John Giannelos
        elif users == None:
1176 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1177 d5cc50b3 John Giannelos
        else:
1178 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1179 d5cc50b3 John Giannelos
1180 d5cc50b3 John Giannelos
        hostip = self._get_ipv4(server)
1181 740a5649 John Giannelos
        myPass = self.password['B']
1182 740a5649 John Giannelos
1183 2bcfb712 John Giannelos
        log.info("SSH in server B as %s/%s" % (loginname, myPass))
1184 1b40b5e3 John Giannelos
1185 88736f65 John Giannelos
        res = False
1186 88736f65 John Giannelos
1187 d5cc50b3 John Giannelos
        if loginname != "root":
1188 88736f65 John Giannelos
            with settings(
1189 33ae1493 John Giannelos
                hide('warnings', 'running'),
1190 8252d64f John Giannelos
                warn_only=True,
1191 8252d64f John Giannelos
                host_string=hostip,
1192 8252d64f John Giannelos
                user=loginname, password=myPass
1193 88736f65 John Giannelos
                ):
1194 8252d64f John Giannelos
1195 2bcfb712 John Giannelos
                if len(sudo('ifconfig eth1 192.168.0.13')) == 0:
1196 88736f65 John Giannelos
                    res = True
1197 8252d64f John Giannelos
1198 2bcfb712 John Giannelos
        else:
1199 ae139e8a John Giannelos
            with settings(
1200 33ae1493 John Giannelos
                hide('warnings', 'running'),
1201 8252d64f John Giannelos
                warn_only=True,
1202 8252d64f John Giannelos
                host_string=hostip,
1203 8252d64f John Giannelos
                user=loginname, password=myPass
1204 ae139e8a John Giannelos
                ):
1205 ae139e8a John Giannelos
1206 33ae1493 John Giannelos
                if len(run('ifconfig eth1 192.168.0.13')) == 0:
1207 ae139e8a John Giannelos
                    res = True
1208 ae139e8a John Giannelos
1209 88736f65 John Giannelos
        self.assertTrue(res)
1210 ae139e8a John Giannelos
1211 88736f65 John Giannelos
    def test_003c_test_connection_exists(self):
1212 4573ea07 John Giannelos
        """Ping server B from server A to test if connection exists"""
1213 1b40b5e3 John Giannelos
1214 e49bdb7c John Giannelos
        self._skipIf(self.is_windows, "only valid for Linux servers")
1215 e49bdb7c John Giannelos
1216 f89d0238 John Giannelos
        log.info("Testing if server A is actually connected to server B")
1217 f89d0238 John Giannelos
1218 1b40b5e3 John Giannelos
        server = self.client.get_server_details(self.serverid['A'])
1219 08748d73 John Giannelos
        image = self.client.get_image_details(self.imageid)
1220 1b40b5e3 John Giannelos
        os = image['metadata']['values']['os']
1221 1b40b5e3 John Giannelos
        hostip = self._get_ipv4(server)
1222 d5cc50b3 John Giannelos
1223 d5cc50b3 John Giannelos
        users = image["metadata"]["values"].get("users", None)
1224 d5cc50b3 John Giannelos
        userlist = users.split()
1225 d5cc50b3 John Giannelos
1226 d5cc50b3 John Giannelos
        if "root" in userlist:
1227 d5cc50b3 John Giannelos
            loginname = "root"
1228 d5cc50b3 John Giannelos
        elif users == None:
1229 1b40b5e3 John Giannelos
            loginname = self._connect_loginname(os)
1230 d5cc50b3 John Giannelos
        else:
1231 d5cc50b3 John Giannelos
            loginname = choice(userlist)
1232 1b40b5e3 John Giannelos
1233 88736f65 John Giannelos
        myPass = self.password['A']
1234 88736f65 John Giannelos
1235 1b40b5e3 John Giannelos
        try:
1236 1b40b5e3 John Giannelos
            ssh = paramiko.SSHClient()
1237 1b40b5e3 John Giannelos
            ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
1238 8252d64f John Giannelos
            ssh.connect(hostip, username=loginname, password=myPass)
1239 1b40b5e3 John Giannelos
        except socket.error:
1240 1b40b5e3 John Giannelos
            raise AssertionError
1241 1b40b5e3 John Giannelos
1242 8252d64f John Giannelos
        cmd = "if ping -c 2 -w 3 192.168.0.13 >/dev/null; \
1243 8252d64f John Giannelos
               then echo \'True\'; fi;"
1244 1b40b5e3 John Giannelos
        stdin, stdout, stderr = ssh.exec_command(cmd)
1245 1b40b5e3 John Giannelos
        lines = stdout.readlines()
1246 1b40b5e3 John Giannelos
1247 740a5649 John Giannelos
        exists = False
1248 4573ea07 John Giannelos
1249 88736f65 John Giannelos
        if 'True\n' in lines:
1250 88736f65 John Giannelos
            exists = True
1251 1b40b5e3 John Giannelos
1252 1b40b5e3 John Giannelos
        self.assertTrue(exists)
1253 1b40b5e3 John Giannelos
1254 88736f65 John Giannelos
    def test_004_disconnect_from_network(self):
1255 4573ea07 John Giannelos
        "Disconnecting server A and B from network"
1256 4573ea07 John Giannelos
1257 f89d0238 John Giannelos
        log.info("Disconnecting servers from private network")
1258 f89d0238 John Giannelos
1259 f97dce4d John Giannelos
        prev_state = self.client.get_network_details(self.networkid)
1260 9e4682b5 John Giannelos
        prev_conn = len(prev_state['servers']['values'])
1261 e94a9d8c John Giannelos
1262 91de9b55 John Giannelos
        self.client.disconnect_server(self.serverid['A'], self.networkid)
1263 91de9b55 John Giannelos
        self.client.disconnect_server(self.serverid['B'], self.networkid)
1264 f97dce4d John Giannelos
1265 65462ca9 John Giannelos
        #Insist on deleting until action timeout
1266 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1267 9e4682b5 John Giannelos
1268 65462ca9 John Giannelos
        while True:
1269 de2461ec John Giannelos
            connected = (self.client.get_network_details(self.networkid))
1270 65462ca9 John Giannelos
            connections = connected['servers']['values']
1271 8252d64f John Giannelos
            if ((self.serverid['A'] not in connections) and
1272 8252d64f John Giannelos
                (self.serverid['B'] not in connections)):
1273 65462ca9 John Giannelos
                conn_exists = False
1274 de2461ec John Giannelos
                break
1275 de2461ec John Giannelos
            elif time.time() > fail_tmout:
1276 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1277 65462ca9 John Giannelos
            else:
1278 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1279 65462ca9 John Giannelos
1280 65462ca9 John Giannelos
        self.assertFalse(conn_exists)
1281 9e4682b5 John Giannelos
1282 88736f65 John Giannelos
    def test_005_destroy_network(self):
1283 e94a9d8c John Giannelos
        """Test submit delete network request"""
1284 f89d0238 John Giannelos
1285 f89d0238 John Giannelos
        log.info("Submitting delete network request")
1286 f89d0238 John Giannelos
1287 8252d64f John Giannelos
        self.client.delete_network(self.networkid)
1288 9e4682b5 John Giannelos
        networks = self.client.list_networks()
1289 e94a9d8c John Giannelos
1290 65462ca9 John Giannelos
        curr_net = []
1291 65462ca9 John Giannelos
        for net in networks:
1292 de2461ec John Giannelos
            curr_net.append(net['id'])
1293 65462ca9 John Giannelos
1294 65462ca9 John Giannelos
        self.assertTrue(self.networkid not in curr_net)
1295 8252d64f John Giannelos
1296 88736f65 John Giannelos
    def test_006_cleanup_servers(self):
1297 65462ca9 John Giannelos
        """Cleanup servers created for this test"""
1298 f89d0238 John Giannelos
1299 f89d0238 John Giannelos
        log.info("Delete servers created for this test")
1300 f89d0238 John Giannelos
1301 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['A'])
1302 91de9b55 John Giannelos
        self.compute.delete_server(self.serverid['B'])
1303 91de9b55 John Giannelos
1304 2bcfb712 John Giannelos
        fail_tmout = time.time() + self.action_timeout
1305 65462ca9 John Giannelos
1306 65462ca9 John Giannelos
        #Ensure server gets deleted
1307 8252d64f John Giannelos
        status = dict()
1308 91de9b55 John Giannelos
1309 65462ca9 John Giannelos
        while True:
1310 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['A'])
1311 91de9b55 John Giannelos
            status['A'] = details['status']
1312 91de9b55 John Giannelos
            details = self.compute.get_server_details(self.serverid['B'])
1313 91de9b55 John Giannelos
            status['B'] = details['status']
1314 91de9b55 John Giannelos
            if (status['A'] == 'DELETED') and (status['B'] == 'DELETED'):
1315 65462ca9 John Giannelos
                deleted = True
1316 de2461ec John Giannelos
                break
1317 8252d64f John Giannelos
            elif time.time() > fail_tmout:
1318 65462ca9 John Giannelos
                self.assertLess(time.time(), fail_tmout)
1319 65462ca9 John Giannelos
            else:
1320 65462ca9 John Giannelos
                time.sleep(self.query_interval)
1321 8252d64f John Giannelos
1322 65462ca9 John Giannelos
        self.assertTrue(deleted)
1323 e94a9d8c John Giannelos
1324 4573ea07 John Giannelos
1325 21bbbc9b Vangelis Koukis
class TestRunnerProcess(Process):
1326 21bbbc9b Vangelis Koukis
    """A distinct process used to execute part of the tests in parallel"""
1327 21bbbc9b Vangelis Koukis
    def __init__(self, **kw):
1328 21bbbc9b Vangelis Koukis
        Process.__init__(self, **kw)
1329 96da37c8 John Giannelos
        kwargs = kw["kwargs"]
1330 21bbbc9b Vangelis Koukis
        self.testq = kwargs["testq"]
1331 21bbbc9b Vangelis Koukis
        self.runner = kwargs["runner"]
1332 21bbbc9b Vangelis Koukis
1333 21bbbc9b Vangelis Koukis
    def run(self):
1334 21bbbc9b Vangelis Koukis
        # Make sure this test runner process dies with the parent
1335 21bbbc9b Vangelis Koukis
        # and is not left behind.
1336 21bbbc9b Vangelis Koukis
        #
1337 21bbbc9b Vangelis Koukis
        # WARNING: This uses the prctl(2) call and is
1338 21bbbc9b Vangelis Koukis
        # Linux-specific.
1339 21bbbc9b Vangelis Koukis
        prctl.set_pdeathsig(signal.SIGHUP)
1340 21bbbc9b Vangelis Koukis
1341 21bbbc9b Vangelis Koukis
        while True:
1342 21bbbc9b Vangelis Koukis
            log.debug("I am process %d, GETting from queue is %s",
1343 21bbbc9b Vangelis Koukis
                     os.getpid(), self.testq)
1344 21bbbc9b Vangelis Koukis
            msg = self.testq.get()
1345 21bbbc9b Vangelis Koukis
            log.debug("Dequeued msg: %s", msg)
1346 21bbbc9b Vangelis Koukis
1347 21bbbc9b Vangelis Koukis
            if msg == "TEST_RUNNER_TERMINATE":
1348 21bbbc9b Vangelis Koukis
                raise SystemExit
1349 21bbbc9b Vangelis Koukis
            elif issubclass(msg, unittest.TestCase):
1350 21bbbc9b Vangelis Koukis
                # Assemble a TestSuite, and run it
1351 21bbbc9b Vangelis Koukis
                suite = unittest.TestLoader().loadTestsFromTestCase(msg)
1352 21bbbc9b Vangelis Koukis
                self.runner.run(suite)
1353 21bbbc9b Vangelis Koukis
            else:
1354 21bbbc9b Vangelis Koukis
                raise Exception("Cannot handle msg: %s" % msg)
1355 21bbbc9b Vangelis Koukis
1356 21bbbc9b Vangelis Koukis
1357 21bbbc9b Vangelis Koukis
def _run_cases_in_parallel(cases, fanout=1, runner=None):
1358 21bbbc9b Vangelis Koukis
    """Run instances of TestCase in parallel, in a number of distinct processes
1359 21bbbc9b Vangelis Koukis

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

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

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

1674 5a140b23 Vangelis Koukis
    """
1675 ae139e8a John Giannelos
1676 5a140b23 Vangelis Koukis
    (opts, args) = parse_arguments(sys.argv[1:])
1677 5a140b23 Vangelis Koukis
1678 946da8b6 John Giannelos
    global API, TOKEN, PLANKTON, PLANKTON_USER, NO_IPV6
1679 21bbbc9b Vangelis Koukis
    API = opts.api
1680 21bbbc9b Vangelis Koukis
    TOKEN = opts.token
1681 946da8b6 John Giannelos
    PLANKTON = opts.plankton
1682 946da8b6 John Giannelos
    PLANKTON_USER = opts.plankton_user
1683 946da8b6 John Giannelos
    NO_IPV6 = opts.no_ipv6
1684 21bbbc9b Vangelis Koukis
1685 5a140b23 Vangelis Koukis
    # Cleanup stale servers from previous runs
1686 5a140b23 Vangelis Koukis
    if opts.show_stale:
1687 c0448f4f John Giannelos
        cleanup_servers(delete_stale=opts.delete_stale, timeout=opts.action_timeout, query_interval=opts.query_interval)
1688 c0448f4f John Giannelos
        cleanup_networks(delete_stale=opts.delete_stale, timeout=opts.action_timeout, query_interval=opts.query_interval)
1689 74ec726f John Giannelos
        return 0
1690 5a140b23 Vangelis Koukis
1691 5a140b23 Vangelis Koukis
    # Initialize a kamaki instance, get flavors, images
1692 96da37c8 John Giannelos
    c = ComputeClient(API, TOKEN)
1693 74193008 John Giannelos
1694 5a140b23 Vangelis Koukis
    DIMAGES = c.list_images(detail=True)
1695 5a140b23 Vangelis Koukis
    DFLAVORS = c.list_flavors(detail=True)
1696 5a140b23 Vangelis Koukis
1697 21bbbc9b Vangelis Koukis
    # FIXME: logging, log, LOG PID, TEST_RUN_ID, arguments
1698 5a140b23 Vangelis Koukis
    # Run them: FIXME: In parallel, FAILEARLY, catchbreak?
1699 5a140b23 Vangelis Koukis
    #unittest.main(verbosity=2, catchbreak=True)
1700 5a140b23 Vangelis Koukis
1701 e94a9d8c John Giannelos
    if opts.force_imageid == 'all':
1702 e94a9d8c John Giannelos
        test_images = DIMAGES
1703 e94a9d8c John Giannelos
    else:
1704 e94a9d8c John Giannelos
        test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
1705 e94a9d8c John Giannelos
1706 81e8cbf6 John Giannelos
    #New folder for log per image
1707 74ec726f John Giannelos
    if not os.path.exists(opts.log_folder):
1708 74ec726f John Giannelos
        os.mkdir(opts.log_folder)
1709 74ec726f John Giannelos
1710 2bcfb712 John Giannelos
    test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
1711 74ec726f John Giannelos
    os.mkdir(test_folder)
1712 81e8cbf6 John Giannelos
1713 00f87624 Vangelis Koukis
    for image in test_images:
1714 8252d64f John Giannelos
1715 99d41650 John Giannelos
        imageid = str(image["id"])
1716 8252d64f John Giannelos
1717 81e8cbf6 John Giannelos
        if opts.force_flavorid:
1718 81e8cbf6 John Giannelos
            flavorid = opts.force_flavorid
1719 81e8cbf6 John Giannelos
        else:
1720 81e8cbf6 John Giannelos
            flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
1721 81e8cbf6 John Giannelos
1722 21bbbc9b Vangelis Koukis
        imagename = image["name"]
1723 8252d64f John Giannelos
1724 567ffb85 John Giannelos
        #Personality dictionary for file injection test
1725 9659e075 John Giannelos
        if opts.personality_path != None:
1726 9659e075 John Giannelos
            f = open(opts.personality_path)
1727 9659e075 John Giannelos
            content = b64encode(f.read())
1728 9659e075 John Giannelos
            personality = []
1729 9659e075 John Giannelos
            st = os.stat(opts.personality_path)
1730 9659e075 John Giannelos
            personality.append({
1731 9659e075 John Giannelos
                    'path': '/root/test_inj_file',
1732 9659e075 John Giannelos
                    'owner': 'root',
1733 9659e075 John Giannelos
                    'group': 'root',
1734 9659e075 John Giannelos
                    'mode': 0x7777 & st.st_mode,
1735 9659e075 John Giannelos
                    'contents': content
1736 9659e075 John Giannelos
                    })
1737 9659e075 John Giannelos
        else:
1738 9659e075 John Giannelos
            personality = None
1739 9659e075 John Giannelos
1740 21bbbc9b Vangelis Koukis
        servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
1741 21bbbc9b Vangelis Koukis
        is_windows = imagename.lower().find("windows") >= 0
1742 8252d64f John Giannelos
1743 8252d64f John Giannelos
        ServerTestCase = _spawn_server_test_case(
1744 8252d64f John Giannelos
            imageid=imageid,
1745 8252d64f John Giannelos
            flavorid=flavorid,
1746 8252d64f John Giannelos
            imagename=imagename,
1747 8252d64f John Giannelos
            personality=personality,
1748 8252d64f John Giannelos
            servername=servername,
1749 8252d64f John Giannelos
            is_windows=is_windows,
1750 8252d64f John Giannelos
            action_timeout=opts.action_timeout,
1751 8252d64f John Giannelos
            build_warning=opts.build_warning,
1752 8252d64f John Giannelos
            build_fail=opts.build_fail,
1753 8252d64f John Giannelos
            query_interval=opts.query_interval,
1754 8252d64f John Giannelos
            )
1755 8252d64f 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 81e8cbf6 John Giannelos
        for case in seq_cases:
1784 746540cd John Giannelos
1785 746540cd John Giannelos
            test = (key for key, value in test_dict.items()
1786 746540cd John Giannelos
                    if value == case).next()
1787 746540cd John Giannelos
1788 746540cd John Giannelos
            log.info(yellow + '* Starting testcase: %s' %test + normal)
1789 8252d64f John Giannelos
            log_file = os.path.join(image_folder, 'details_' +
1790 8252d64f John Giannelos
                                    (case.__name__) + "_" +
1791 8252d64f John Giannelos
                                    TEST_RUN_ID + '.log')
1792 8252d64f John Giannelos
            fail_file = os.path.join(image_folder, 'failed_' +
1793 8252d64f John Giannelos
                                     (case.__name__) + "_" +
1794 8252d64f John Giannelos
                                     TEST_RUN_ID + '.log')
1795 8252d64f John Giannelos
            error_file = os.path.join(image_folder, 'error_' +
1796 8252d64f John Giannelos
                                      (case.__name__) + "_" +
1797 8252d64f John Giannelos
                                      TEST_RUN_ID + '.log')
1798 81e8cbf6 John Giannelos
1799 81e8cbf6 John Giannelos
            f = open(log_file, "w")
1800 81e8cbf6 John Giannelos
            fail = open(fail_file, "w")
1801 81e8cbf6 John Giannelos
            error = open(error_file, "w")
1802 81e8cbf6 John Giannelos
1803 81e8cbf6 John Giannelos
            suite = unittest.TestLoader().loadTestsFromTestCase(case)
1804 66eba2cf John Giannelos
            runner = unittest.TextTestRunner(f, verbosity=2, failfast=True, resultclass=BurninTestResult)
1805 81e8cbf6 John Giannelos
            result = runner.run(suite)
1806 8252d64f John Giannelos
1807 81e8cbf6 John Giannelos
            for res in result.errors:
1808 746540cd John Giannelos
                log.error("snf-burnin encountered an error in " \
1809 746540cd John Giannelos
                              "testcase: %s" %test)
1810 746540cd John Giannelos
                log.error("See log for details")
1811 2bcfb712 John Giannelos
                error.write(str(res[0]) + '\n')
1812 74ec726f John Giannelos
                error.write(str(res[0].shortDescription()) + '\n')
1813 81e8cbf6 John Giannelos
                error.write('\n')
1814 4d6e355c John Giannelos
1815 aa388d48 John Giannelos
            for res in result.failures:
1816 746540cd John Giannelos
                log.error("snf-burnin failed in testcase: %s" %test)
1817 746540cd John Giannelos
                log.error("See log for details")
1818 2bcfb712 John Giannelos
                fail.write(str(res[0]) + '\n')
1819 74ec726f John Giannelos
                fail.write(str(res[0].shortDescription()) + '\n')
1820 aa388d48 John Giannelos
                fail.write('\n')
1821 e8a6a168 John Giannelos
                if opts.nofailfast == False:
1822 e8a6a168 John Giannelos
                    sys.exit()
1823 8252d64f John Giannelos
1824 746540cd John Giannelos
            if (len(result.failures) == 0) and (len(result.errors) == 0):
1825 746540cd John Giannelos
                log.debug("Passed testcase: %s" %test)
1826 746540cd John Giannelos
1827 5a140b23 Vangelis Koukis
if __name__ == "__main__":
1828 5a140b23 Vangelis Koukis
    sys.exit(main())