35 |
35 |
|
36 |
36 |
"""Perform integration testing on a running Synnefo deployment"""
|
37 |
37 |
|
38 |
|
import __main__
|
|
38 |
#import __main__
|
39 |
39 |
import datetime
|
40 |
40 |
import inspect
|
41 |
41 |
import logging
|
... | ... | |
58 |
58 |
from kamaki.clients.image import ImageClient
|
59 |
59 |
from kamaki.clients import ClientError
|
60 |
60 |
|
61 |
|
from fabric.api import *
|
|
61 |
import fabric.api as fabric
|
62 |
62 |
|
63 |
63 |
from vncauthproxy.d3des import generate_response as d3des_generate_response
|
64 |
64 |
|
... | ... | |
70 |
70 |
raise Exception("The unittest2 package is required for Python < 2.7")
|
71 |
71 |
import unittest
|
72 |
72 |
|
|
73 |
# --------------------------------------------------------------------
|
|
74 |
# Global Variables
|
|
75 |
API = None
|
|
76 |
TOKEN = None
|
|
77 |
PLANKTON = None
|
|
78 |
PLANKTON_USER = None
|
|
79 |
NO_IPV6 = None
|
|
80 |
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
|
|
81 |
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
|
|
82 |
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
|
|
83 |
NOFAILFAST = None
|
|
84 |
VERBOSE = None
|
|
85 |
|
|
86 |
# A unique id identifying this test run
|
|
87 |
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
|
|
88 |
"%Y%m%d%H%M%S")
|
|
89 |
SNF_TEST_PREFIX = "snf-test-"
|
|
90 |
|
|
91 |
red = '\x1b[31m'
|
|
92 |
yellow = '\x1b[33m'
|
|
93 |
green = '\x1b[32m'
|
|
94 |
normal = '\x1b[0m'
|
|
95 |
|
73 |
96 |
|
|
97 |
# --------------------------------------------------------------------
|
|
98 |
# BurninTestReulst class
|
74 |
99 |
class BurninTestResult(unittest.TextTestResult):
|
75 |
100 |
def addSuccess(self, test):
|
76 |
101 |
super(BurninTestResult, self).addSuccess(test)
|
... | ... | |
85 |
110 |
|
86 |
111 |
elif self.dots:
|
87 |
112 |
self.stream.write('.')
|
88 |
|
self.stream.flush()
|
89 |
|
|
|
113 |
self.stream.flush()
|
|
114 |
|
90 |
115 |
def addError(self, test, err):
|
91 |
116 |
super(BurninTestResult, self).addError(test, err)
|
92 |
117 |
if self.showAll:
|
... | ... | |
120 |
145 |
self.stream.flush()
|
121 |
146 |
|
122 |
147 |
|
123 |
|
|
124 |
|
API = None
|
125 |
|
TOKEN = None
|
126 |
|
DEFAULT_API = "https://cyclades.okeanos.grnet.gr/api/v1.1"
|
127 |
|
DEFAULT_PLANKTON = "https://cyclades.okeanos.grnet.gr/plankton"
|
128 |
|
DEFAULT_PLANKTON_USER = "images@okeanos.grnet.gr"
|
129 |
|
|
130 |
|
# A unique id identifying this test run
|
131 |
|
TEST_RUN_ID = datetime.datetime.strftime(datetime.datetime.now(),
|
132 |
|
"%Y%m%d%H%M%S")
|
133 |
|
SNF_TEST_PREFIX = "snf-test-"
|
134 |
|
|
135 |
|
red = '\x1b[31m'
|
136 |
|
yellow = '\x1b[33m'
|
137 |
|
green = '\x1b[32m'
|
138 |
|
normal = '\x1b[0m'
|
139 |
|
|
|
148 |
# --------------------------------------------------------------------
|
|
149 |
# Format Results
|
140 |
150 |
class burninFormatter(logging.Formatter):
|
141 |
|
|
142 |
151 |
err_fmt = red + "ERROR: %(msg)s" + normal
|
143 |
152 |
dbg_fmt = green + "* %(msg)s" + normal
|
144 |
153 |
info_fmt = "%(msg)s"
|
... | ... | |
147 |
156 |
logging.Formatter.__init__(self, fmt)
|
148 |
157 |
|
149 |
158 |
def format(self, record):
|
150 |
|
|
151 |
159 |
format_orig = self._fmt
|
152 |
|
|
153 |
160 |
# Replace the original format with one customized by logging level
|
154 |
161 |
if record.levelno == 10: # DEBUG
|
155 |
162 |
self._fmt = burninFormatter.dbg_fmt
|
156 |
|
|
157 |
163 |
elif record.levelno == 20: # INFO
|
158 |
164 |
self._fmt = burninFormatter.info_fmt
|
159 |
|
|
160 |
165 |
elif record.levelno == 40: # ERROR
|
161 |
166 |
self._fmt = burninFormatter.err_fmt
|
162 |
|
|
163 |
167 |
result = logging.Formatter.format(self, record)
|
164 |
168 |
self._fmt = format_orig
|
165 |
|
|
166 |
169 |
return result
|
167 |
170 |
|
168 |
171 |
log = logging.getLogger("burnin")
|
... | ... | |
172 |
175 |
log.addHandler(handler)
|
173 |
176 |
|
174 |
177 |
|
|
178 |
# --------------------------------------------------------------------
|
|
179 |
# UnauthorizedTestCase class
|
175 |
180 |
class UnauthorizedTestCase(unittest.TestCase):
|
176 |
|
|
|
181 |
"""Test unauthorized access"""
|
177 |
182 |
@classmethod
|
178 |
183 |
def setUpClass(cls):
|
179 |
184 |
cls.result_dict = dict()
|
... | ... | |
181 |
186 |
def test_unauthorized_access(self):
|
182 |
187 |
"""Test access without a valid token fails"""
|
183 |
188 |
log.info("Authentication test")
|
184 |
|
|
185 |
189 |
falseToken = '12345'
|
186 |
190 |
c = ComputeClient(API, falseToken)
|
187 |
191 |
|
... | ... | |
190 |
194 |
self.assertEqual(cm.exception.status, 401)
|
191 |
195 |
|
192 |
196 |
|
|
197 |
# --------------------------------------------------------------------
|
|
198 |
# ImagesTestCase class
|
193 |
199 |
class ImagesTestCase(unittest.TestCase):
|
194 |
200 |
"""Test image lists for consistency"""
|
195 |
201 |
@classmethod
|
196 |
202 |
def setUpClass(cls):
|
197 |
203 |
"""Initialize kamaki, get (detailed) list of images"""
|
198 |
204 |
log.info("Getting simple and detailed list of images")
|
199 |
|
|
200 |
205 |
cls.client = ComputeClient(API, TOKEN)
|
201 |
206 |
cls.plankton = ImageClient(PLANKTON, TOKEN)
|
202 |
207 |
cls.images = cls.plankton.list_public()
|
... | ... | |
232 |
237 |
self.assertTrue(keys.issubset(i["metadata"]["values"].keys()))
|
233 |
238 |
|
234 |
239 |
|
|
240 |
# --------------------------------------------------------------------
|
|
241 |
# FlavorsTestCase class
|
235 |
242 |
class FlavorsTestCase(unittest.TestCase):
|
236 |
243 |
"""Test flavor lists for consistency"""
|
237 |
244 |
@classmethod
|
238 |
245 |
def setUpClass(cls):
|
239 |
246 |
"""Initialize kamaki, get (detailed) list of flavors"""
|
240 |
247 |
log.info("Getting simple and detailed list of flavors")
|
241 |
|
|
242 |
248 |
cls.client = ComputeClient(API, TOKEN)
|
243 |
249 |
cls.flavors = cls.client.list_flavors()
|
244 |
250 |
cls.dflavors = cls.client.list_flavors(detail=True)
|
... | ... | |
265 |
271 |
|
266 |
272 |
def test_005_well_formed_flavor_names(self):
|
267 |
273 |
"""Test flavors have names of the form CxxRyyDzz
|
268 |
|
|
269 |
274 |
Where xx is vCPU count, yy is RAM in MiB, zz is Disk in GiB
|
270 |
|
|
271 |
275 |
"""
|
272 |
276 |
for f in self.dflavors:
|
273 |
277 |
self.assertEqual("C%dR%dD%d" % (f["cpu"], f["ram"], f["disk"]),
|
... | ... | |
275 |
279 |
"Flavor %s does not match its specs." % f["name"])
|
276 |
280 |
|
277 |
281 |
|
|
282 |
# --------------------------------------------------------------------
|
|
283 |
# ServersTestCase class
|
278 |
284 |
class ServersTestCase(unittest.TestCase):
|
279 |
285 |
"""Test server lists for consistency"""
|
280 |
286 |
@classmethod
|
... | ... | |
309 |
315 |
@classmethod
|
310 |
316 |
def setUpClass(cls):
|
311 |
317 |
"""Initialize a kamaki instance"""
|
312 |
|
log.info("Spawning server for image `%s'" %cls.imagename)
|
|
318 |
log.info("Spawning server for image `%s'" % cls.imagename)
|
313 |
319 |
cls.client = ComputeClient(API, TOKEN)
|
314 |
320 |
cls.cyclades = CycladesClient(API, TOKEN)
|
315 |
321 |
cls.result_dict = dict()
|
... | ... | |
321 |
327 |
|
322 |
328 |
for nic in nics:
|
323 |
329 |
net_id = nic["network_id"]
|
324 |
|
if self.cyclades.get_network_details(net_id)["public"] == True:
|
|
330 |
if self.cyclades.get_network_details(net_id)["public"]:
|
325 |
331 |
public_addrs = nic["ipv4"]
|
326 |
|
|
327 |
|
self.assertTrue(public_addrs != None)
|
|
332 |
|
|
333 |
self.assertTrue(public_addrs is not None)
|
328 |
334 |
|
329 |
335 |
return public_addrs
|
330 |
336 |
|
... | ... | |
335 |
341 |
|
336 |
342 |
for nic in nics:
|
337 |
343 |
net_id = nic["network_id"]
|
338 |
|
if self.cyclades.get_network_details(net_id)["public"] == True:
|
|
344 |
if self.cyclades.get_network_details(net_id)["public"]:
|
339 |
345 |
public_addrs = nic["ipv6"]
|
340 |
|
|
341 |
|
self.assertTrue(public_addrs != None)
|
342 |
346 |
|
343 |
|
return public_addrs
|
|
347 |
self.assertTrue(public_addrs is not None)
|
344 |
348 |
|
|
349 |
return public_addrs
|
345 |
350 |
|
346 |
|
def _connect_loginname(self, os):
|
|
351 |
def _connect_loginname(self, os_value):
|
347 |
352 |
"""Return the login name for connections based on the server OS"""
|
348 |
|
if os in ("Ubuntu", "Kubuntu", "Fedora"):
|
|
353 |
if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
|
349 |
354 |
return "user"
|
350 |
|
elif os in ("windows", "windows_alpha1"):
|
|
355 |
elif os_value in ("windows", "windows_alpha1"):
|
351 |
356 |
return "Administrator"
|
352 |
357 |
else:
|
353 |
358 |
return "root"
|
... | ... | |
368 |
373 |
af, socktype, proto, canonname, sa = res
|
369 |
374 |
try:
|
370 |
375 |
sock = socket.socket(af, socktype, proto)
|
371 |
|
except socket.error as msg:
|
|
376 |
except socket.error:
|
372 |
377 |
sock = None
|
373 |
378 |
continue
|
374 |
379 |
try:
|
375 |
380 |
sock.connect(sa)
|
376 |
|
except socket.error as msg:
|
|
381 |
except socket.error:
|
377 |
382 |
sock.close()
|
378 |
383 |
sock = None
|
379 |
384 |
continue
|
... | ... | |
426 |
431 |
msg = "connect over %s to %s:%s" % \
|
427 |
432 |
(familystr.get(family, "Unknown"), host, port)
|
428 |
433 |
sock = self._try_until_timeout_expires(
|
429 |
|
self.action_timeout, self.action_timeout,
|
430 |
|
msg, self._get_connected_tcp_socket,
|
431 |
|
family, host, port)
|
|
434 |
self.action_timeout, self.action_timeout,
|
|
435 |
msg, self._get_connected_tcp_socket,
|
|
436 |
family, host, port)
|
432 |
437 |
return sock
|
433 |
438 |
|
434 |
439 |
def _insist_on_status_transition(self, current_status, new_status,
|
435 |
|
fail_timeout, warn_timeout=None):
|
|
440 |
fail_timeout, warn_timeout=None):
|
436 |
441 |
msg = "Server %d: `%s', waiting for %s -> %s" % \
|
437 |
442 |
(self.serverid, self.servername, current_status, new_status)
|
438 |
443 |
if warn_timeout is None:
|
... | ... | |
447 |
452 |
def _insist_on_ssh_hostname(self, hostip, username, password):
|
448 |
453 |
msg = "SSH to %s, as %s/%s" % (hostip, username, password)
|
449 |
454 |
hostname = self._try_until_timeout_expires(
|
450 |
|
self.action_timeout, self.action_timeout,
|
451 |
|
msg, self._get_hostname_over_ssh,
|
452 |
|
hostip, username, password)
|
|
455 |
self.action_timeout, self.action_timeout,
|
|
456 |
msg, self._get_hostname_over_ssh,
|
|
457 |
hostip, username, password)
|
453 |
458 |
|
454 |
459 |
# The hostname must be of the form 'prefix-id'
|
455 |
460 |
self.assertTrue(hostname.endswith("-%d\n" % self.serverid))
|
... | ... | |
539 |
544 |
log.info("Creating server metadata")
|
540 |
545 |
|
541 |
546 |
image = self.client.get_image_details(self.imageid)
|
542 |
|
os = image["metadata"]["values"]["os"]
|
|
547 |
os_value = image["metadata"]["values"]["os"]
|
543 |
548 |
users = image["metadata"]["values"].get("users", None)
|
544 |
|
self.client.update_server_metadata(self.serverid, OS=os)
|
|
549 |
self.client.update_server_metadata(self.serverid, OS=os_value)
|
545 |
550 |
|
546 |
551 |
userlist = users.split()
|
547 |
552 |
|
... | ... | |
551 |
556 |
|
552 |
557 |
if "root" in userlist:
|
553 |
558 |
cls.username = "root"
|
554 |
|
elif users == None:
|
555 |
|
cls.username = self._connect_loginname(os)
|
|
559 |
elif users is None:
|
|
560 |
cls.username = self._connect_loginname(os_value)
|
556 |
561 |
else:
|
557 |
562 |
cls.username = choice(userlist)
|
558 |
563 |
|
... | ... | |
573 |
578 |
|
574 |
579 |
log.info("Waiting for server to become ACTIVE")
|
575 |
580 |
|
576 |
|
self._insist_on_status_transition("BUILD", "ACTIVE",
|
577 |
|
self.build_fail, self.build_warning)
|
|
581 |
self._insist_on_status_transition(
|
|
582 |
"BUILD", "ACTIVE", self.build_fail, self.build_warning)
|
578 |
583 |
|
579 |
584 |
def test_003a_get_server_oob_console(self):
|
580 |
585 |
"""Test getting OOB server console over VNC
|
... | ... | |
585 |
590 |
"""
|
586 |
591 |
console = self.cyclades.get_server_console(self.serverid)
|
587 |
592 |
self.assertEquals(console['type'], "vnc")
|
588 |
|
sock = self._insist_on_tcp_connection(socket.AF_INET,
|
589 |
|
console["host"], console["port"])
|
|
593 |
sock = self._insist_on_tcp_connection(
|
|
594 |
socket.AF_INET, console["host"], console["port"])
|
590 |
595 |
|
591 |
596 |
# Step 1. ProtocolVersion message (par. 6.1.1)
|
592 |
597 |
version = sock.recv(1024)
|
... | ... | |
619 |
624 |
|
620 |
625 |
log.info("Validate server's IPv4")
|
621 |
626 |
|
622 |
|
|
623 |
627 |
server = self.client.get_server_details(self.serverid)
|
624 |
628 |
ipv4 = self._get_ipv4(server)
|
625 |
629 |
|
... | ... | |
680 |
684 |
"""Test server becomes STOPPED"""
|
681 |
685 |
|
682 |
686 |
log.info("Waiting until server becomes STOPPED")
|
683 |
|
self._insist_on_status_transition("ACTIVE", "STOPPED",
|
684 |
|
self.action_timeout,
|
685 |
|
self.action_timeout)
|
|
687 |
self._insist_on_status_transition(
|
|
688 |
"ACTIVE", "STOPPED", self.action_timeout, self.action_timeout)
|
686 |
689 |
|
687 |
690 |
def test_010_submit_start_request(self):
|
688 |
691 |
"""Test submit start server request"""
|
... | ... | |
695 |
698 |
"""Test server becomes ACTIVE again"""
|
696 |
699 |
|
697 |
700 |
log.info("Waiting until server becomes ACTIVE")
|
698 |
|
self._insist_on_status_transition("STOPPED", "ACTIVE",
|
699 |
|
self.action_timeout,
|
700 |
|
self.action_timeout)
|
|
701 |
self._insist_on_status_transition(
|
|
702 |
"STOPPED", "ACTIVE", self.action_timeout, self.action_timeout)
|
701 |
703 |
|
702 |
704 |
def test_011a_server_responds_to_ping_IPv4(self):
|
703 |
705 |
"""Test server OS is actually up and running again"""
|
... | ... | |
728 |
730 |
self._skipIf(not self.is_windows, "only valid for Windows servers")
|
729 |
731 |
server = self.client.get_server_details(self.serverid)
|
730 |
732 |
ipv4 = self._get_ipv4(server)
|
731 |
|
sock = _insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
|
|
733 |
sock = self._insist_on_tcp_connection(socket.AF_INET, ipv4, 3389)
|
732 |
734 |
|
733 |
735 |
# No actual RDP processing done. We assume the RDP server is there
|
734 |
736 |
# if the connection to the RDP port is successful.
|
... | ... | |
742 |
744 |
|
743 |
745 |
server = self.client.get_server_details(self.serverid)
|
744 |
746 |
ipv6 = self._get_ipv6(server)
|
745 |
|
sock = _get_tcp_connection(socket.AF_INET6, ipv6, 3389)
|
|
747 |
sock = self._get_tcp_connection(socket.AF_INET6, ipv6, 3389)
|
746 |
748 |
|
747 |
749 |
# No actual RDP processing done. We assume the RDP server is there
|
748 |
750 |
# if the connection to the RDP port is successful.
|
... | ... | |
751 |
753 |
def test_016_personality_is_enforced(self):
|
752 |
754 |
"""Test file injection for personality enforcement"""
|
753 |
755 |
self._skipIf(self.is_windows, "only implemented for Linux servers")
|
754 |
|
self._skipIf(self.personality == None, "No personality file selected")
|
|
756 |
self._skipIf(self.personality is None, "No personality file selected")
|
755 |
757 |
|
756 |
758 |
log.info("Trying to inject file for personality enforcement")
|
757 |
759 |
|
... | ... | |
777 |
779 |
|
778 |
780 |
log.info("Testing if server becomes DELETED")
|
779 |
781 |
|
780 |
|
self._insist_on_status_transition("ACTIVE", "DELETED",
|
781 |
|
self.action_timeout,
|
782 |
|
self.action_timeout)
|
|
782 |
self._insist_on_status_transition(
|
|
783 |
"ACTIVE", "DELETED", self.action_timeout, self.action_timeout)
|
783 |
784 |
|
784 |
785 |
def test_019_server_no_longer_in_server_list(self):
|
785 |
786 |
"""Test server is no longer in server list"""
|
... | ... | |
823 |
824 |
|
824 |
825 |
for nic in nics:
|
825 |
826 |
net_id = nic["network_id"]
|
826 |
|
if self.client.get_network_details(net_id)["public"] == True:
|
|
827 |
if self.client.get_network_details(net_id)["public"]:
|
827 |
828 |
public_addrs = nic["ipv4"]
|
828 |
|
|
829 |
|
self.assertTrue(public_addrs != None)
|
830 |
829 |
|
831 |
|
return public_addrs
|
|
830 |
self.assertTrue(public_addrs is not None)
|
832 |
831 |
|
|
832 |
return public_addrs
|
833 |
833 |
|
834 |
|
def _connect_loginname(self, os):
|
|
834 |
def _connect_loginname(self, os_value):
|
835 |
835 |
"""Return the login name for connections based on the server OS"""
|
836 |
|
if os in ("Ubuntu", "Kubuntu", "Fedora"):
|
|
836 |
if os_value in ("Ubuntu", "Kubuntu", "Fedora"):
|
837 |
837 |
return "user"
|
838 |
|
elif os in ("windows", "windows_alpha1"):
|
|
838 |
elif os_value in ("windows", "windows_alpha1"):
|
839 |
839 |
return "Administrator"
|
840 |
840 |
else:
|
841 |
841 |
return "root"
|
... | ... | |
874 |
874 |
|
875 |
875 |
self.result_dict["Server A ID"] = str(serverA["id"])
|
876 |
876 |
self.result_dict["Server A password"] = serverA["adminPass"]
|
877 |
|
|
|
877 |
|
878 |
878 |
def test_00001b_serverA_becomes_active(self):
|
879 |
879 |
"""Test server becomes ACTIVE"""
|
880 |
880 |
|
... | ... | |
899 |
899 |
"""Test submit create server request"""
|
900 |
900 |
|
901 |
901 |
log.info("Creating test server B")
|
902 |
|
|
|
902 |
|
903 |
903 |
serverB = self.client.create_server(self.servername, self.flavorid,
|
904 |
904 |
self.imageid, personality=None)
|
905 |
905 |
|
... | ... | |
945 |
945 |
|
946 |
946 |
log.info("Submit new network request")
|
947 |
947 |
self.result_dict.clear()
|
948 |
|
|
|
948 |
|
949 |
949 |
name = SNF_TEST_PREFIX + TEST_RUN_ID
|
950 |
|
previous_num = len(self.client.list_networks())
|
951 |
|
network = self.client.create_network(name,cidr='10.0.0.1/28')
|
|
950 |
#previous_num = len(self.client.list_networks())
|
|
951 |
network = self.client.create_network(name, cidr='10.0.0.1/28')
|
952 |
952 |
|
953 |
953 |
#Test if right name is assigned
|
954 |
954 |
self.assertEqual(network['name'], name)
|
... | ... | |
956 |
956 |
# Update class attributes
|
957 |
957 |
cls = type(self)
|
958 |
958 |
cls.networkid = network['id']
|
959 |
|
networks = self.client.list_networks()
|
|
959 |
#networks = self.client.list_networks()
|
960 |
960 |
|
961 |
961 |
fail_tmout = time.time() + self.action_timeout
|
962 |
962 |
|
... | ... | |
990 |
990 |
|
991 |
991 |
while True:
|
992 |
992 |
|
993 |
|
netsA = [x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
|
994 |
|
netsB = [x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
|
|
993 |
netsA = [x['network_id']
|
|
994 |
for x in self.client.get_server_details(
|
|
995 |
self.serverid['A'])['attachments']['values']]
|
|
996 |
netsB = [x['network_id']
|
|
997 |
for x in self.client.get_server_details(
|
|
998 |
self.serverid['B'])['attachments']['values']]
|
995 |
999 |
|
996 |
1000 |
if (self.networkid in netsA) and (self.networkid in netsB):
|
997 |
1001 |
conn_exists = True
|
... | ... | |
1000 |
1004 |
self.assertLess(time.time(), fail_tmout)
|
1001 |
1005 |
else:
|
1002 |
1006 |
time.sleep(self.query_interval)
|
1003 |
|
|
|
1007 |
|
1004 |
1008 |
#Adding private IPs to class attributes
|
1005 |
1009 |
cls = type(self)
|
1006 |
1010 |
cls.priv_ip = dict()
|
1007 |
1011 |
|
1008 |
|
nicsA = self.client.get_server_details(self.serverid['A'])['attachments']['values']
|
1009 |
|
nicsB = self.client.get_server_details(self.serverid['B'])['attachments']['values']
|
|
1012 |
nicsA = self.client.get_server_details(
|
|
1013 |
self.serverid['A'])['attachments']['values']
|
|
1014 |
nicsB = self.client.get_server_details(
|
|
1015 |
self.serverid['B'])['attachments']['values']
|
1010 |
1016 |
|
1011 |
1017 |
if conn_exists:
|
1012 |
1018 |
for nic in nicsA:
|
... | ... | |
1064 |
1070 |
fail_tmout = time.time() + self.action_timeout
|
1065 |
1071 |
|
1066 |
1072 |
s = False
|
1067 |
|
|
|
1073 |
|
1068 |
1074 |
self.result_dict["Server A public IP"] = str(ip)
|
1069 |
1075 |
|
1070 |
1076 |
while True:
|
... | ... | |
1120 |
1126 |
|
1121 |
1127 |
log.info("Testing if server B responds to IPv4 pings")
|
1122 |
1128 |
self.result_dict.clear()
|
1123 |
|
|
|
1129 |
|
1124 |
1130 |
server = self.client.get_server_details(self.serverid['B'])
|
1125 |
1131 |
ip = self._get_ipv4(server)
|
1126 |
1132 |
|
... | ... | |
1153 |
1159 |
|
1154 |
1160 |
server = self.client.get_server_details(self.serverid['A'])
|
1155 |
1161 |
image = self.client.get_image_details(self.imageid)
|
1156 |
|
os = image['metadata']['values']['os']
|
|
1162 |
os_value = image['metadata']['values']['os']
|
1157 |
1163 |
|
1158 |
1164 |
users = image["metadata"]["values"].get("users", None)
|
1159 |
1165 |
userlist = users.split()
|
1160 |
1166 |
|
1161 |
1167 |
if "root" in userlist:
|
1162 |
1168 |
loginname = "root"
|
1163 |
|
elif users == None:
|
1164 |
|
loginname = self._connect_loginname(os)
|
|
1169 |
elif users is None:
|
|
1170 |
loginname = self._connect_loginname(os_value)
|
1165 |
1171 |
else:
|
1166 |
1172 |
loginname = choice(userlist)
|
1167 |
1173 |
|
... | ... | |
1173 |
1179 |
res = False
|
1174 |
1180 |
|
1175 |
1181 |
if loginname != "root":
|
1176 |
|
with settings(
|
1177 |
|
hide('warnings', 'running'),
|
1178 |
|
warn_only=True,
|
1179 |
|
host_string=hostip,
|
1180 |
|
user=loginname, password=myPass
|
1181 |
|
):
|
1182 |
|
|
1183 |
|
if len(sudo('ifconfig eth1 %s' % self.priv_ip["A"])) == 0:
|
|
1182 |
with fabric.settings(
|
|
1183 |
fabric.hide('warnings', 'running'),
|
|
1184 |
warn_only=True,
|
|
1185 |
host_string=hostip,
|
|
1186 |
user=loginname, password=myPass):
|
|
1187 |
conf_res = fabric.sudo('ifconfig eth1 %s' % self.priv_ip["A"])
|
|
1188 |
if len(conf_res) == 0:
|
1184 |
1189 |
res = True
|
1185 |
1190 |
|
1186 |
1191 |
else:
|
1187 |
|
with settings(
|
1188 |
|
hide('warnings', 'running'),
|
1189 |
|
warn_only=True,
|
1190 |
|
host_string=hostip,
|
1191 |
|
user=loginname, password=myPass
|
1192 |
|
):
|
1193 |
|
|
1194 |
|
if len(run('ifconfig eth1 %s' % self.priv_ip["A"])) == 0:
|
|
1192 |
with fabric.settings(
|
|
1193 |
fabric.hide('warnings', 'running'),
|
|
1194 |
warn_only=True,
|
|
1195 |
host_string=hostip,
|
|
1196 |
user=loginname, password=myPass):
|
|
1197 |
conf_res = fabric.run('ifconfig eth1 %s' % self.priv_ip["A"])
|
|
1198 |
if len(conf_res) == 0:
|
1195 |
1199 |
res = True
|
1196 |
1200 |
|
1197 |
1201 |
self.assertTrue(res)
|
... | ... | |
1205 |
1209 |
|
1206 |
1210 |
server = self.client.get_server_details(self.serverid['B'])
|
1207 |
1211 |
image = self.client.get_image_details(self.imageid)
|
1208 |
|
os = image['metadata']['values']['os']
|
|
1212 |
os_value = image['metadata']['values']['os']
|
1209 |
1213 |
|
1210 |
1214 |
users = image["metadata"]["values"].get("users", None)
|
1211 |
1215 |
userlist = users.split()
|
1212 |
1216 |
|
1213 |
1217 |
if "root" in userlist:
|
1214 |
1218 |
loginname = "root"
|
1215 |
|
elif users == None:
|
1216 |
|
loginname = self._connect_loginname(os)
|
|
1219 |
elif users is None:
|
|
1220 |
loginname = self._connect_loginname(os_value)
|
1217 |
1221 |
else:
|
1218 |
1222 |
loginname = choice(userlist)
|
1219 |
1223 |
|
... | ... | |
1225 |
1229 |
res = False
|
1226 |
1230 |
|
1227 |
1231 |
if loginname != "root":
|
1228 |
|
with settings(
|
1229 |
|
hide('warnings', 'running'),
|
1230 |
|
warn_only=True,
|
1231 |
|
host_string=hostip,
|
1232 |
|
user=loginname, password=myPass
|
1233 |
|
):
|
1234 |
|
|
1235 |
|
if len(sudo('ifconfig eth1 %s' % self.priv_ip["B"])) == 0:
|
|
1232 |
with fabric.settings(
|
|
1233 |
fabric.hide('warnings', 'running'),
|
|
1234 |
warn_only=True,
|
|
1235 |
host_string=hostip,
|
|
1236 |
user=loginname, password=myPass):
|
|
1237 |
conf_res = fabric.sudo('ifconfig eth1 %s' % self.priv_ip["B"])
|
|
1238 |
if len(conf_res) == 0:
|
1236 |
1239 |
res = True
|
1237 |
1240 |
|
1238 |
1241 |
else:
|
1239 |
|
with settings(
|
1240 |
|
hide('warnings', 'running'),
|
1241 |
|
warn_only=True,
|
1242 |
|
host_string=hostip,
|
1243 |
|
user=loginname, password=myPass
|
1244 |
|
):
|
1245 |
|
|
1246 |
|
if len(run('ifconfig eth1 %s' % self.priv_ip["B"])) == 0:
|
|
1242 |
with fabric.settings(
|
|
1243 |
fabric.hide('warnings', 'running'),
|
|
1244 |
warn_only=True,
|
|
1245 |
host_string=hostip,
|
|
1246 |
user=loginname, password=myPass):
|
|
1247 |
conf_res = fabric.run('ifconfig eth1 %s' % self.priv_ip["B"])
|
|
1248 |
if len(conf_res) == 0:
|
1247 |
1249 |
res = True
|
1248 |
1250 |
|
1249 |
1251 |
self.assertTrue(res)
|
... | ... | |
1257 |
1259 |
|
1258 |
1260 |
server = self.client.get_server_details(self.serverid['A'])
|
1259 |
1261 |
image = self.client.get_image_details(self.imageid)
|
1260 |
|
os = image['metadata']['values']['os']
|
|
1262 |
os_value = image['metadata']['values']['os']
|
1261 |
1263 |
hostip = self._get_ipv4(server)
|
1262 |
1264 |
|
1263 |
1265 |
users = image["metadata"]["values"].get("users", None)
|
... | ... | |
1265 |
1267 |
|
1266 |
1268 |
if "root" in userlist:
|
1267 |
1269 |
loginname = "root"
|
1268 |
|
elif users == None:
|
1269 |
|
loginname = self._connect_loginname(os)
|
|
1270 |
elif users is None:
|
|
1271 |
loginname = self._connect_loginname(os_value)
|
1270 |
1272 |
else:
|
1271 |
1273 |
loginname = choice(userlist)
|
1272 |
1274 |
|
... | ... | |
1298 |
1300 |
|
1299 |
1301 |
prev_state = self.client.get_network_details(self.networkid)
|
1300 |
1302 |
prev_nics = prev_state['attachments']['values']
|
1301 |
|
prev_conn = len(prev_nics)
|
|
1303 |
#prev_conn = len(prev_nics)
|
1302 |
1304 |
|
1303 |
|
nicsA=[x['id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
|
1304 |
|
nicsB=[x['id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
|
|
1305 |
nicsA = [x['id']
|
|
1306 |
for x in self.client.get_server_details(
|
|
1307 |
self.serverid['A'])['attachments']['values']]
|
|
1308 |
nicsB = [x['id']
|
|
1309 |
for x in self.client.get_server_details(
|
|
1310 |
self.serverid['B'])['attachments']['values']]
|
1305 |
1311 |
|
1306 |
1312 |
for nic in prev_nics:
|
1307 |
1313 |
if nic in nicsA:
|
... | ... | |
1309 |
1315 |
if nic in nicsB:
|
1310 |
1316 |
self.client.disconnect_server(self.serverid['B'], nic)
|
1311 |
1317 |
|
1312 |
|
|
1313 |
1318 |
#Insist on deleting until action timeout
|
1314 |
1319 |
fail_tmout = time.time() + self.action_timeout
|
1315 |
1320 |
|
1316 |
1321 |
while True:
|
1317 |
|
|
1318 |
|
netsA=[x['network_id'] for x in self.client.get_server_details(self.serverid['A'])['attachments']['values']]
|
1319 |
|
netsB=[x['network_id'] for x in self.client.get_server_details(self.serverid['B'])['attachments']['values']]
|
1320 |
|
|
1321 |
|
|
1322 |
|
connected = (self.client.get_network_details(self.networkid))
|
1323 |
|
connections = connected['attachments']['values']
|
|
1322 |
netsA = [x['network_id']
|
|
1323 |
for x in self.client.get_server_details(
|
|
1324 |
self.serverid['A'])['attachments']['values']]
|
|
1325 |
netsB = [x['network_id']
|
|
1326 |
for x in self.client.get_server_details(
|
|
1327 |
self.serverid['B'])['attachments']['values']]
|
|
1328 |
|
|
1329 |
#connected = (self.client.get_network_details(self.networkid))
|
|
1330 |
#connections = connected['attachments']['values']
|
1324 |
1331 |
if (self.networkid not in netsA) and (self.networkid not in netsB):
|
1325 |
1332 |
conn_exists = False
|
1326 |
1333 |
break
|
... | ... | |
1358 |
1365 |
else:
|
1359 |
1366 |
time.sleep(self.query_interval)
|
1360 |
1367 |
|
1361 |
|
|
1362 |
|
|
1363 |
1368 |
def test_006_cleanup_servers(self):
|
1364 |
1369 |
"""Cleanup servers created for this test"""
|
1365 |
1370 |
|
... | ... | |
1410 |
1415 |
|
1411 |
1416 |
while True:
|
1412 |
1417 |
multi.debug("I am process %d, GETting from queue is %s" %
|
1413 |
|
(os.getpid(), self.testq))
|
|
1418 |
(os.getpid(), self.testq))
|
1414 |
1419 |
msg = self.testq.get()
|
1415 |
1420 |
|
1416 |
1421 |
multi.debug("Dequeued msg: %s" % msg)
|
... | ... | |
1433 |
1438 |
TEST_RUN_ID + '.log')
|
1434 |
1439 |
|
1435 |
1440 |
f = open(log_file, 'w')
|
1436 |
|
fail = open(fail_file,'w')
|
|
1441 |
fail = open(fail_file, 'w')
|
1437 |
1442 |
error = open(error_file, 'w')
|
1438 |
1443 |
|
1439 |
1444 |
log.info(yellow + '* Starting testcase: %s' % msg + normal)
|
1440 |
1445 |
|
1441 |
|
runner = unittest.TextTestRunner(f, verbosity=2, failfast = True, resultclass=BurninTestResult)
|
|
1446 |
runner = unittest.TextTestRunner(
|
|
1447 |
f, verbosity=2, failfast=True,
|
|
1448 |
resultclass=BurninTestResult)
|
1442 |
1449 |
suite = unittest.TestLoader().loadTestsFromTestCase(msg)
|
1443 |
1450 |
result = runner.run(suite)
|
1444 |
1451 |
|
1445 |
1452 |
for res in result.errors:
|
1446 |
|
log.error("snf-burnin encountered an error in " \
|
1447 |
|
"testcase: %s" %msg)
|
|
1453 |
log.error("snf-burnin encountered an error in "
|
|
1454 |
"testcase: %s" % msg)
|
1448 |
1455 |
log.error("See log for details")
|
1449 |
1456 |
error.write(str(res[0]) + '\n')
|
1450 |
1457 |
error.write(str(res[0].shortDescription()) + '\n')
|
1451 |
1458 |
error.write('\n')
|
1452 |
1459 |
|
1453 |
1460 |
for res in result.failures:
|
1454 |
|
log.error("snf-burnin failed in testcase: %s" %msg)
|
|
1461 |
log.error("snf-burnin failed in testcase: %s" % msg)
|
1455 |
1462 |
log.error("See log for details")
|
1456 |
1463 |
fail.write(str(res[0]) + '\n')
|
1457 |
1464 |
fail.write(str(res[0].shortDescription()) + '\n')
|
1458 |
1465 |
fail.write('\n')
|
1459 |
|
if NOFAILFAST == False:
|
|
1466 |
if not NOFAILFAST:
|
1460 |
1467 |
sys.exit()
|
1461 |
1468 |
|
1462 |
1469 |
if (len(result.failures) == 0) and (len(result.errors) == 0):
|
1463 |
|
log.debug("Passed testcase: %s" %msg)
|
|
1470 |
log.debug("Passed testcase: %s" % msg)
|
1464 |
1471 |
|
1465 |
1472 |
f.close()
|
1466 |
1473 |
fail.close()
|
1467 |
1474 |
error.close()
|
1468 |
1475 |
|
1469 |
|
|
1470 |
1476 |
else:
|
1471 |
1477 |
raise Exception("Cannot handle msg: %s" % msg)
|
1472 |
1478 |
|
1473 |
|
def _run_cases_in_series(cases,image_folder):
|
|
1479 |
|
|
1480 |
def _run_cases_in_series(cases, image_folder):
|
1474 |
1481 |
"""Run instances of TestCase in series"""
|
1475 |
1482 |
|
1476 |
1483 |
for case in cases:
|
1477 |
1484 |
|
1478 |
1485 |
test = case.__name__
|
1479 |
1486 |
|
1480 |
|
log.info(yellow + '* Starting testcase: %s' %test + normal)
|
|
1487 |
log.info(yellow + '* Starting testcase: %s' % test + normal)
|
1481 |
1488 |
log_file = os.path.join(image_folder, 'details_' +
|
1482 |
1489 |
(case.__name__) + "_" +
|
1483 |
1490 |
TEST_RUN_ID + '.log')
|
... | ... | |
1493 |
1500 |
error = open(error_file, "w")
|
1494 |
1501 |
|
1495 |
1502 |
suite = unittest.TestLoader().loadTestsFromTestCase(case)
|
1496 |
|
runner = unittest.TextTestRunner(f, verbosity=2, failfast=True, resultclass=BurninTestResult)
|
|
1503 |
runner = unittest.TextTestRunner(
|
|
1504 |
f, verbosity=2, failfast=True,
|
|
1505 |
resultclass=BurninTestResult)
|
1497 |
1506 |
result = runner.run(suite)
|
1498 |
1507 |
|
1499 |
1508 |
for res in result.errors:
|
1500 |
|
log.error("snf-burnin encountered an error in " \
|
1501 |
|
"testcase: %s" %test)
|
|
1509 |
log.error("snf-burnin encountered an error in "
|
|
1510 |
"testcase: %s" % test)
|
1502 |
1511 |
log.error("See log for details")
|
1503 |
1512 |
error.write(str(res[0]) + '\n')
|
1504 |
1513 |
error.write(str(res[0].shortDescription()) + '\n')
|
1505 |
1514 |
error.write('\n')
|
1506 |
1515 |
|
1507 |
1516 |
for res in result.failures:
|
1508 |
|
log.error("snf-burnin failed in testcase: %s" %test)
|
|
1517 |
log.error("snf-burnin failed in testcase: %s" % test)
|
1509 |
1518 |
log.error("See log for details")
|
1510 |
1519 |
fail.write(str(res[0]) + '\n')
|
1511 |
1520 |
fail.write(str(res[0].shortDescription()) + '\n')
|
1512 |
1521 |
fail.write('\n')
|
1513 |
|
if NOFAILFAST == False:
|
|
1522 |
if not NOFAILFAST:
|
1514 |
1523 |
sys.exit()
|
1515 |
1524 |
|
1516 |
1525 |
if (len(result.failures) == 0) and (len(result.errors) == 0):
|
1517 |
|
log.debug("Passed testcase: %s" %test)
|
|
1526 |
log.debug("Passed testcase: %s" % test)
|
1518 |
1527 |
|
1519 |
|
|
1520 |
1528 |
|
1521 |
1529 |
def _run_cases_in_parallel(cases, fanout, image_folder):
|
1522 |
1530 |
"""Run instances of TestCase in parallel, in a number of distinct processes
|
... | ... | |
1543 |
1551 |
worker_folder = []
|
1544 |
1552 |
runners = []
|
1545 |
1553 |
|
1546 |
|
for i in xrange(0,fanout):
|
|
1554 |
for i in xrange(0, fanout):
|
1547 |
1555 |
testq.append(Queue())
|
1548 |
1556 |
worker_folder.append(os.path.join(image_folder, 'process'+str(i)))
|
1549 |
1557 |
os.mkdir(worker_folder[i])
|
... | ... | |
1552 |
1560 |
kwargs = dict(testq=testq[i], worker_folder=worker_folder[i])
|
1553 |
1561 |
runners.append(TestRunnerProcess(kwargs=kwargs))
|
1554 |
1562 |
|
1555 |
|
multi.debug("Spawning %d test runner processes" %len(runners))
|
|
1563 |
multi.debug("Spawning %d test runner processes" % len(runners))
|
1556 |
1564 |
|
1557 |
1565 |
for p in runners:
|
1558 |
1566 |
p.start()
|
... | ... | |
1563 |
1571 |
testq[i].put("TEST_RUNNER_TERMINATE")
|
1564 |
1572 |
|
1565 |
1573 |
multi.debug("Spawned %d test runners, PIDs are %s" %
|
1566 |
|
(len(runners), [p.pid for p in runners]))
|
|
1574 |
(len(runners), [p.pid for p in runners]))
|
1567 |
1575 |
|
1568 |
1576 |
multi.debug("Joining %d processes" % len(runners))
|
1569 |
1577 |
|
... | ... | |
1581 |
1589 |
|
1582 |
1590 |
# Patch extra parameters into test names by manipulating method docstrings
|
1583 |
1591 |
for (mname, m) in \
|
1584 |
|
inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
|
|
1592 |
inspect.getmembers(cls, lambda x: inspect.ismethod(x)):
|
1585 |
1593 |
if hasattr(m, __doc__):
|
1586 |
|
m.__func__.__doc__ = "[%s] %s" % (imagename, m.__doc__)
|
|
1594 |
m.__func__.__doc__ = "[%s] %s" % (cls.imagename, m.__doc__)
|
1587 |
1595 |
|
1588 |
1596 |
# Make sure the class can be pickled, by listing it among
|
1589 |
1597 |
# the attributes of __main__. A PicklingError is raised otherwise.
|
... | ... | |
1621 |
1629 |
|
1622 |
1630 |
# Show staled servers
|
1623 |
1631 |
print >>sys.stderr, yellow + \
|
1624 |
|
"Found these stale servers from previous runs:" + \
|
1625 |
|
normal
|
|
1632 |
"Found these stale servers from previous runs:" + \
|
|
1633 |
normal
|
1626 |
1634 |
print >>sys.stderr, " " + \
|
1627 |
|
"\n ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
|
|
1635 |
"\n ".join(["%d: %s" % (s["id"], s["name"]) for s in stale])
|
1628 |
1636 |
|
1629 |
1637 |
# Delete staled servers
|
1630 |
1638 |
if delete_stale:
|
... | ... | |
1635 |
1643 |
# Wait for all servers to be deleted
|
1636 |
1644 |
while True:
|
1637 |
1645 |
servers = c.list_servers()
|
1638 |
|
stale = [s for s in servers if s["name"].startswith(SNF_TEST_PREFIX)]
|
1639 |
|
if len(stale)==0:
|
|
1646 |
stale = [s for s in servers
|
|
1647 |
if s["name"].startswith(SNF_TEST_PREFIX)]
|
|
1648 |
if len(stale) == 0:
|
1640 |
1649 |
print >> sys.stderr, green + " ...done" + normal
|
1641 |
1650 |
break
|
1642 |
1651 |
elif time.time() > fail_tmout:
|
1643 |
1652 |
print >> sys.stderr, red + \
|
1644 |
|
"Not all stale servers deleted. Action timed out." + \
|
1645 |
|
normal
|
1646 |
|
return
|
|
1653 |
"Not all stale servers deleted. Action timed out." + \
|
|
1654 |
normal
|
|
1655 |
sys.exit(1)
|
1647 |
1656 |
else:
|
1648 |
1657 |
time.sleep(query_interval)
|
1649 |
1658 |
else:
|
... | ... | |
1662 |
1671 |
|
1663 |
1672 |
# Show staled networks
|
1664 |
1673 |
print >> sys.stderr, yellow + \
|
1665 |
|
"Found these stale networks from previous runs:" + \
|
1666 |
|
normal
|
|
1674 |
"Found these stale networks from previous runs:" + \
|
|
1675 |
normal
|
1667 |
1676 |
print " " + \
|
1668 |
|
"\n ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
|
|
1677 |
"\n ".join(["%s: %s" % (str(n["id"]), n["name"]) for n in stale])
|
1669 |
1678 |
|
1670 |
1679 |
# Delete staled networks
|
1671 |
1680 |
if delete_stale:
|
... | ... | |
1676 |
1685 |
# Wait for all networks to be deleted
|
1677 |
1686 |
while True:
|
1678 |
1687 |
networks = c.list_networks()
|
1679 |
|
stale = [n for n in networks if n["name"].startswith(SNF_TEST_PREFIX)]
|
1680 |
|
if len(stale)==0:
|
|
1688 |
stale = [n for n in networks
|
|
1689 |
if n["name"].startswith(SNF_TEST_PREFIX)]
|
|
1690 |
if len(stale) == 0:
|
1681 |
1691 |
print >> sys.stderr, green + " ...done" + normal
|
1682 |
1692 |
break
|
1683 |
1693 |
elif time.time() > fail_tmout:
|
1684 |
1694 |
print >> sys.stderr, red + \
|
1685 |
|
"Not all stale networks deleted. Action timed out." + \
|
1686 |
|
normal
|
1687 |
|
return
|
|
1695 |
"Not all stale networks deleted. Action timed out." + \
|
|
1696 |
normal
|
|
1697 |
sys.exit(1)
|
1688 |
1698 |
else:
|
1689 |
1699 |
time.sleep(query_interval)
|
1690 |
1700 |
else:
|
... | ... | |
1695 |
1705 |
# Parse arguments functions
|
1696 |
1706 |
def parse_comma(option, opt, value, parser):
|
1697 |
1707 |
tests = set(['all', 'auth', 'images', 'flavors',
|
1698 |
|
'servers', 'server_spawn', 'network_spawn'])
|
|
1708 |
'servers', 'server_spawn', 'network_spawn'])
|
1699 |
1709 |
parse_input = value.split(',')
|
1700 |
1710 |
|
1701 |
1711 |
if not (set(parse_input)).issubset(tests):
|
... | ... | |
1732 |
1742 |
help="The token to use for authentication to the API")
|
1733 |
1743 |
parser.add_option("--nofailfast",
|
1734 |
1744 |
action="store_true", dest="nofailfast",
|
1735 |
|
help="Do not fail immediately if one of the tests " \
|
|
1745 |
help="Do not fail immediately if one of the tests "
|
1736 |
1746 |
"fails (EXPERIMENTAL)",
|
1737 |
1747 |
default=False)
|
1738 |
1748 |
parser.add_option("--no-ipv6",
|
... | ... | |
1742 |
1752 |
parser.add_option("--action-timeout",
|
1743 |
1753 |
action="store", type="int", dest="action_timeout",
|
1744 |
1754 |
metavar="TIMEOUT",
|
1745 |
|
help="Wait SECONDS seconds for a server action to " \
|
|
1755 |
help="Wait SECONDS seconds for a server action to "
|
1746 |
1756 |
"complete, then the test is considered failed",
|
1747 |
1757 |
default=100)
|
1748 |
1758 |
parser.add_option("--build-warning",
|
1749 |
1759 |
action="store", type="int", dest="build_warning",
|
1750 |
1760 |
metavar="TIMEOUT",
|
1751 |
|
help="Warn if TIMEOUT seconds have passed and a " \
|
|
1761 |
help="Warn if TIMEOUT seconds have passed and a "
|
1752 |
1762 |
"build operation is still pending",
|
1753 |
1763 |
default=600)
|
1754 |
1764 |
parser.add_option("--build-fail",
|
1755 |
1765 |
action="store", type="int", dest="build_fail",
|
1756 |
1766 |
metavar="BUILD_TIMEOUT",
|
1757 |
|
help="Fail the test if TIMEOUT seconds have passed " \
|
|
1767 |
help="Fail the test if TIMEOUT seconds have passed "
|
1758 |
1768 |
"and a build operation is still incomplete",
|
1759 |
1769 |
default=900)
|
1760 |
1770 |
parser.add_option("--query-interval",
|
1761 |
1771 |
action="store", type="int", dest="query_interval",
|
1762 |
1772 |
metavar="INTERVAL",
|
1763 |
|
help="Query server status when requests are pending " \
|
|
1773 |
help="Query server status when requests are pending "
|
1764 |
1774 |
"every INTERVAL seconds",
|
1765 |
1775 |
default=3)
|
1766 |
1776 |
parser.add_option("--fanout",
|
1767 |
1777 |
action="store", type="int", dest="fanout",
|
1768 |
1778 |
metavar="COUNT",
|
1769 |
|
help="Spawn up to COUNT child processes to execute " \
|
1770 |
|
"in parallel, essentially have up to COUNT " \
|
|
1779 |
help="Spawn up to COUNT child processes to execute "
|
|
1780 |
"in parallel, essentially have up to COUNT "
|
1771 |
1781 |
"server build requests outstanding (EXPERIMENTAL)",
|
1772 |
1782 |
default=1)
|
1773 |
1783 |
parser.add_option("--force-flavor",
|
1774 |
1784 |
action="store", type="int", dest="force_flavorid",
|
1775 |
1785 |
metavar="FLAVOR ID",
|
1776 |
|
help="Force all server creations to use the specified "\
|
1777 |
|
"FLAVOR ID instead of a randomly chosen one, " \
|
|
1786 |
help="Force all server creations to use the specified "
|
|
1787 |
"FLAVOR ID instead of a randomly chosen one, "
|
1778 |
1788 |
"useful if disk space is scarce",
|
1779 |
1789 |
default=None)
|
1780 |
1790 |
parser.add_option("--image-id",
|
1781 |
1791 |
action="store", type="string", dest="force_imageid",
|
1782 |
1792 |
metavar="IMAGE ID",
|
1783 |
|
help="Test the specified image id, use 'all' to test " \
|
|
1793 |
help="Test the specified image id, use 'all' to test "
|
1784 |
1794 |
"all available images (mandatory argument)",
|
1785 |
1795 |
default=None)
|
1786 |
1796 |
parser.add_option("--show-stale",
|
1787 |
1797 |
action="store_true", dest="show_stale",
|
1788 |
|
help="Show stale servers from previous runs, whose "\
|
|
1798 |
help="Show stale servers from previous runs, whose "
|
1789 |
1799 |
"name starts with `%s'" % SNF_TEST_PREFIX,
|
1790 |
1800 |
default=False)
|
1791 |
1801 |
parser.add_option("--delete-stale",
|
1792 |
1802 |
action="store_true", dest="delete_stale",
|
1793 |
|
help="Delete stale servers from previous runs, whose "\
|
|
1803 |
help="Delete stale servers from previous runs, whose "
|
1794 |
1804 |
"name starts with `%s'" % SNF_TEST_PREFIX,
|
1795 |
1805 |
default=False)
|
1796 |
1806 |
parser.add_option("--force-personality",
|
... | ... | |
1805 |
1815 |
default="/var/log/burnin/")
|
1806 |
1816 |
parser.add_option("--verbose", "-V",
|
1807 |
1817 |
action="store_true", dest="verbose",
|
1808 |
|
help="Print detailed output about multiple "\
|
|
1818 |
help="Print detailed output about multiple "
|
1809 |
1819 |
"processes spawning",
|
1810 |
1820 |
default=False)
|
1811 |
1821 |
parser.add_option("--set-tests",
|
... | ... | |
1833 |
1843 |
if not opts.show_stale:
|
1834 |
1844 |
if not opts.force_imageid:
|
1835 |
1845 |
print >>sys.stderr, red + \
|
1836 |
|
"The --image-id argument is mandatory.\n" + \
|
1837 |
|
normal
|
|
1846 |
"The --image-id argument is mandatory.\n" + \
|
|
1847 |
normal
|
1838 |
1848 |
parser.print_help()
|
1839 |
1849 |
sys.exit(1)
|
1840 |
1850 |
if opts.force_imageid != 'all':
|
... | ... | |
1842 |
1852 |
opts.force_imageid = str(opts.force_imageid)
|
1843 |
1853 |
except ValueError:
|
1844 |
1854 |
print >>sys.stderr, red + \
|
1845 |
|
"Invalid value specified for" + \
|
1846 |
|
"--image-id. Use a valid id, or `all'." + \
|
1847 |
|
normal
|
|
1855 |
"Invalid value specified for" + \
|
|
1856 |
"--image-id. Use a valid id, or `all'." + \
|
|
1857 |
normal
|
1848 |
1858 |
sys.exit(1)
|
1849 |
1859 |
|
1850 |
1860 |
# `token' is mandatory
|
1851 |
1861 |
if not opts.token:
|
1852 |
1862 |
print >>sys.stderr, red + \
|
1853 |
|
"The --token argument is mandatory.\n" + \
|
1854 |
|
normal
|
|
1863 |
"The --token argument is mandatory.\n" + \
|
|
1864 |
normal
|
1855 |
1865 |
parser.print_help()
|
1856 |
1866 |
sys.exit(1)
|
1857 |
1867 |
|
... | ... | |
1896 |
1906 |
|
1897 |
1907 |
# Initialize a kamaki instance, get flavors, images
|
1898 |
1908 |
c = ComputeClient(API, TOKEN)
|
1899 |
|
|
1900 |
1909 |
DIMAGES = c.list_images(detail=True)
|
1901 |
1910 |
DFLAVORS = c.list_flavors(detail=True)
|
1902 |
1911 |
|
... | ... | |
1904 |
1913 |
# Run them: FIXME: In parallel, FAILEARLY, catchbreak?
|
1905 |
1914 |
#unittest.main(verbosity=2, catchbreak=True)
|
1906 |
1915 |
|
|
1916 |
# Get a list of images we are going to test
|
1907 |
1917 |
if opts.force_imageid == 'all':
|
1908 |
1918 |
test_images = DIMAGES
|
1909 |
1919 |
else:
|
1910 |
1920 |
test_images = filter(lambda x: x["id"] == opts.force_imageid, DIMAGES)
|
1911 |
1921 |
|
1912 |
|
#New folder for log per image
|
|
1922 |
# Create output (logging) folder
|
1913 |
1923 |
if not os.path.exists(opts.log_folder):
|
1914 |
1924 |
os.mkdir(opts.log_folder)
|
1915 |
|
|
1916 |
1925 |
test_folder = os.path.join(opts.log_folder, TEST_RUN_ID)
|
1917 |
1926 |
os.mkdir(test_folder)
|
1918 |
1927 |
|
1919 |
1928 |
for image in test_images:
|
1920 |
|
|
1921 |
1929 |
imageid = str(image["id"])
|
1922 |
|
|
|
1930 |
imagename = image["name"]
|
|
1931 |
# Choose a flavor (given from user or random)
|
1923 |
1932 |
if opts.force_flavorid:
|
1924 |
1933 |
flavorid = opts.force_flavorid
|
1925 |
1934 |
else:
|
1926 |
1935 |
flavorid = choice([f["id"] for f in DFLAVORS if f["disk"] >= 20])
|
1927 |
|
|
1928 |
|
imagename = image["name"]
|
1929 |
|
|
1930 |
|
#Personality dictionary for file injection test
|
1931 |
|
if opts.personality_path != None:
|
|
1936 |
# Personality dictionary for file injection test
|
|
1937 |
if opts.personality_path is not None:
|
1932 |
1938 |
f = open(opts.personality_path)
|
1933 |
1939 |
content = b64encode(f.read())
|
1934 |
1940 |
personality = []
|
1935 |
1941 |
st = os.stat(opts.personality_path)
|
1936 |
1942 |
personality.append({
|
1937 |
|
'path': '/root/test_inj_file',
|
1938 |
|
'owner': 'root',
|
1939 |
|
'group': 'root',
|
1940 |
|
'mode': 0x7777 & st.st_mode,
|
1941 |
|
'contents': content
|
1942 |
|
})
|
|
1943 |
'path': '/root/test_inj_file',
|
|
1944 |
'owner': 'root',
|
|
1945 |
'group': 'root',
|
|
1946 |
'mode': 0x7777 & st.st_mode,
|
|
1947 |
'contents': content})
|
1943 |
1948 |
else:
|
1944 |
1949 |
personality = None
|
1945 |
|
|
|
1950 |
# Give a name to our test servers
|
1946 |
1951 |
servername = "%s%s for %s" % (SNF_TEST_PREFIX, TEST_RUN_ID, imagename)
|
1947 |
1952 |
is_windows = imagename.lower().find("windows") >= 0
|
1948 |
1953 |
|
|
1954 |
# Create Server TestCases
|
1949 |
1955 |
ServerTestCase = _spawn_server_test_case(
|
1950 |
1956 |
imageid=imageid,
|
1951 |
1957 |
flavorid=flavorid,
|
... | ... | |
1956 |
1962 |
action_timeout=opts.action_timeout,
|
1957 |
1963 |
build_warning=opts.build_warning,
|
1958 |
1964 |
build_fail=opts.build_fail,
|
1959 |
|
query_interval=opts.query_interval,
|
1960 |
|
)
|
1961 |
|
|
1962 |
|
|
|
1965 |
query_interval=opts.query_interval)
|
|
1966 |
# Create Network TestCases
|
1963 |
1967 |
NetworkTestCase = _spawn_network_test_case(
|
1964 |
1968 |
action_timeout=opts.action_timeout,
|
1965 |
1969 |
imageid=imageid,
|
1966 |
1970 |
flavorid=flavorid,
|
1967 |
1971 |
imagename=imagename,
|
1968 |
|
query_interval=opts.query_interval,
|
1969 |
|
)
|
|
1972 |
query_interval=opts.query_interval)
|
1970 |
1973 |
|
|
1974 |
# Choose the tests we are going to run
|
1971 |
1975 |
test_dict = {'auth': UnauthorizedTestCase,
|
1972 |
1976 |
'images': ImagesTestCase,
|
1973 |
1977 |
'flavors': FlavorsTestCase,
|
1974 |
1978 |
'servers': ServersTestCase,
|
1975 |
1979 |
'server_spawn': ServerTestCase,
|
1976 |
1980 |
'network_spawn': NetworkTestCase}
|
1977 |
|
|
1978 |
1981 |
seq_cases = []
|
1979 |
1982 |
if 'all' in opts.tests:
|
1980 |
1983 |
seq_cases = [UnauthorizedTestCase, ImagesTestCase, FlavorsTestCase,
|
... | ... | |
1983 |
1986 |
for test in opts.tests:
|
1984 |
1987 |
seq_cases.append(test_dict[test])
|
1985 |
1988 |
|
1986 |
|
#folder for each image
|
|
1989 |
# Folder for each image
|
1987 |
1990 |
image_folder = os.path.join(test_folder, imageid)
|
1988 |
1991 |
os.mkdir(image_folder)
|
1989 |
1992 |
|
1990 |
|
if opts.fanout>1:
|
|
1993 |
# Run each test
|
|
1994 |
if opts.fanout > 1:
|
1991 |
1995 |
_run_cases_in_parallel(seq_cases, opts.fanout, image_folder)
|
1992 |
1996 |
else:
|
1993 |
|
_run_cases_in_series(seq_cases,image_folder)
|
|
1997 |
_run_cases_in_series(seq_cases, image_folder)
|
|
1998 |
|
1994 |
1999 |
|
|
2000 |
# --------------------------------------------------------------------
|
|
2001 |
# Call main
|
1995 |
2002 |
if __name__ == "__main__":
|
1996 |
2003 |
sys.exit(main())
|