Merge lp:~soren/nova/improve-smoketests into lp:~hudson-openstack/nova/trunk
- improve-smoketests
- Merge into trunk
Proposed by
Soren Hansen
Status: | Merged |
---|---|
Approved by: | Soren Hansen |
Approved revision: | 825 |
Merged at revision: | 835 |
Proposed branch: | lp:~soren/nova/improve-smoketests |
Merge into: | lp:~hudson-openstack/nova/trunk |
Diff against target: |
641 lines (+362/-85) 9 files modified
nova/tests/api/openstack/test_servers.py (+0/-4) run_tests.py (+2/-0) smoketests/base.py (+16/-35) smoketests/proxy.sh (+9/-2) smoketests/public_network_smoketests.py (+0/-6) smoketests/run_tests.py (+310/-0) smoketests/test_admin.py (+0/-7) smoketests/test_netadmin.py (+3/-14) smoketests/test_sysadmin.py (+22/-17) |
To merge this branch: | bzr merge lp:~soren/nova/improve-smoketests |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jesse Andrews (community) | Approve | ||
Vish Ishaya (community) | Approve | ||
Review via email: mp+53922@code.launchpad.net |
Commit message
Make smoketests' exit code reveal whether they were succesful.
Adjust volume tests to check the exact size of the block device, instead of a rounded-off size of the resulting filesystem.
Make proxy.sh work with both variants of netcat.
Description of the change
With these couple of changes, my automated runs of both sysadmin_smoketests and netadmin_smoketests are now succesful.
To post a comment you must log in.
Revision history for this message
Jesse Andrews (anotherjesse) wrote : | # |
lgtm!
I finally got hardware from RAX to run the smoketests on a real cluster after each deploy
review:
Approve
Revision history for this message
OpenStack Infra (hudson-openstack) wrote : | # |
Attempt to merge into lp:nova failed due to conflicts:
text conflict in smoketests/
- 824. By Soren Hansen
-
Merge trunk
- 825. By Soren Hansen
-
pep8
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'nova/tests/api/openstack/test_servers.py' |
2 | --- nova/tests/api/openstack/test_servers.py 2011-03-17 22:24:08 +0000 |
3 | +++ nova/tests/api/openstack/test_servers.py 2011-03-20 19:08:31 +0000 |
4 | @@ -1174,7 +1174,3 @@ |
5 | server = dom.childNodes[0] |
6 | self.assertEquals(server.nodeName, 'server') |
7 | self.assertTrue(server.getAttribute('adminPass').startswith('fake')) |
8 | - |
9 | - |
10 | -if __name__ == "__main__": |
11 | - unittest.main() |
12 | |
13 | === modified file 'run_tests.py' |
14 | --- run_tests.py 2011-02-25 01:04:25 +0000 |
15 | +++ run_tests.py 2011-03-20 19:08:31 +0000 |
16 | @@ -60,6 +60,8 @@ |
17 | import unittest |
18 | import sys |
19 | |
20 | +gettext.install('nova', unicode=1) |
21 | + |
22 | from nose import config |
23 | from nose import core |
24 | from nose import result |
25 | |
26 | === modified file 'smoketests/base.py' |
27 | --- smoketests/base.py 2011-02-23 02:04:08 +0000 |
28 | +++ smoketests/base.py 2011-03-20 19:08:31 +0000 |
29 | @@ -31,17 +31,24 @@ |
30 | SUITE_NAMES = '[image, instance, volume]' |
31 | FLAGS = flags.FLAGS |
32 | flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES) |
33 | +flags.DEFINE_integer('ssh_tries', 3, 'Numer of times to try ssh') |
34 | boto_v6 = None |
35 | |
36 | |
37 | class SmokeTestCase(unittest.TestCase): |
38 | def connect_ssh(self, ip, key_name): |
39 | - # TODO(devcamcar): set a more reasonable connection timeout time |
40 | key = paramiko.RSAKey.from_private_key_file('/tmp/%s.pem' % key_name) |
41 | - client = paramiko.SSHClient() |
42 | - client.set_missing_host_key_policy(paramiko.WarningPolicy()) |
43 | - client.connect(ip, username='root', pkey=key) |
44 | - return client |
45 | + tries = 0 |
46 | + while(True): |
47 | + try: |
48 | + client = paramiko.SSHClient() |
49 | + client.set_missing_host_key_policy(paramiko.WarningPolicy()) |
50 | + client.connect(ip, username='root', pkey=key, timeout=5) |
51 | + return client |
52 | + except (paramiko.AuthenticationException, paramiko.SSHException): |
53 | + tries += 1 |
54 | + if tries == FLAGS.ssh_tries: |
55 | + raise |
56 | |
57 | def can_ping(self, ip, command="ping"): |
58 | """Attempt to ping the specified IP, and give up after 1 second.""" |
59 | @@ -147,8 +154,8 @@ |
60 | except: |
61 | pass |
62 | |
63 | - def bundle_image(self, image, kernel=False): |
64 | - cmd = 'euca-bundle-image -i %s' % image |
65 | + def bundle_image(self, image, tempdir='/tmp', kernel=False): |
66 | + cmd = 'euca-bundle-image -i %s -d %s' % (image, tempdir) |
67 | if kernel: |
68 | cmd += ' --kernel true' |
69 | status, output = commands.getstatusoutput(cmd) |
70 | @@ -157,9 +164,9 @@ |
71 | raise Exception(output) |
72 | return True |
73 | |
74 | - def upload_image(self, bucket_name, image): |
75 | + def upload_image(self, bucket_name, image, tempdir='/tmp'): |
76 | cmd = 'euca-upload-bundle -b ' |
77 | - cmd += '%s -m /tmp/%s.manifest.xml' % (bucket_name, image) |
78 | + cmd += '%s -m %s/%s.manifest.xml' % (bucket_name, tempdir, image) |
79 | status, output = commands.getstatusoutput(cmd) |
80 | if status != 0: |
81 | print '%s -> \n %s' % (cmd, output) |
82 | @@ -183,29 +190,3 @@ |
83 | global TEST_DATA |
84 | self.conn = self.connection_for_env() |
85 | self.data = TEST_DATA |
86 | - |
87 | - |
88 | -def run_tests(suites): |
89 | - argv = FLAGS(sys.argv) |
90 | - if FLAGS.use_ipv6: |
91 | - global boto_v6 |
92 | - boto_v6 = __import__('boto_v6') |
93 | - |
94 | - if not os.getenv('EC2_ACCESS_KEY'): |
95 | - print >> sys.stderr, 'Missing EC2 environment variables. Please ' \ |
96 | - 'source the appropriate novarc file before ' \ |
97 | - 'running this test.' |
98 | - return 1 |
99 | - |
100 | - if FLAGS.suite: |
101 | - try: |
102 | - suite = suites[FLAGS.suite] |
103 | - except KeyError: |
104 | - print >> sys.stderr, 'Available test suites:', \ |
105 | - ', '.join(suites.keys()) |
106 | - return 1 |
107 | - |
108 | - unittest.TextTestRunner(verbosity=2).run(suite) |
109 | - else: |
110 | - for suite in suites.itervalues(): |
111 | - unittest.TextTestRunner(verbosity=2).run(suite) |
112 | |
113 | === modified file 'smoketests/proxy.sh' |
114 | --- smoketests/proxy.sh 2011-02-23 02:04:32 +0000 |
115 | +++ smoketests/proxy.sh 2011-03-20 19:08:31 +0000 |
116 | @@ -11,12 +11,19 @@ |
117 | mkfifo backpipe1 |
118 | mkfifo backpipe2 |
119 | |
120 | +if nc -h 2>&1 | grep -i openbsd |
121 | +then |
122 | + NC_LISTEN="nc -l" |
123 | +else |
124 | + NC_LISTEN="nc -l -p" |
125 | +fi |
126 | + |
127 | # NOTE(vish): proxy metadata on port 80 |
128 | while true; do |
129 | - nc -l -p 80 0<backpipe1 | nc 169.254.169.254 80 1>backpipe1 |
130 | + $NC_LISTEN 80 0<backpipe1 | nc 169.254.169.254 80 1>backpipe1 |
131 | done & |
132 | |
133 | # NOTE(vish): proxy google on port 8080 |
134 | while true; do |
135 | - nc -l -p 8080 0<backpipe2 | nc 74.125.19.99 80 1>backpipe2 |
136 | + $NC_LISTEN 8080 0<backpipe2 | nc 74.125.19.99 80 1>backpipe2 |
137 | done & |
138 | |
139 | === modified file 'smoketests/public_network_smoketests.py' |
140 | --- smoketests/public_network_smoketests.py 2011-02-23 02:04:08 +0000 |
141 | +++ smoketests/public_network_smoketests.py 2011-03-20 19:08:31 +0000 |
142 | @@ -19,10 +19,8 @@ |
143 | import commands |
144 | import os |
145 | import random |
146 | -import socket |
147 | import sys |
148 | import time |
149 | -import unittest |
150 | |
151 | # If ../nova/__init__.py exists, add ../ to Python search path, so that |
152 | # it will override what happens to be installed in /usr/(local/)lib/python... |
153 | @@ -181,7 +179,3 @@ |
154 | self.conn.delete_security_group(security_group_name) |
155 | if 'instance_id' in self.data: |
156 | self.conn.terminate_instances([self.data['instance_id']]) |
157 | - |
158 | -if __name__ == "__main__": |
159 | - suites = {'instance': unittest.makeSuite(InstanceTestsFromPublic)} |
160 | - sys.exit(base.run_tests(suites)) |
161 | |
162 | === added file 'smoketests/run_tests.py' |
163 | --- smoketests/run_tests.py 1970-01-01 00:00:00 +0000 |
164 | +++ smoketests/run_tests.py 2011-03-20 19:08:31 +0000 |
165 | @@ -0,0 +1,310 @@ |
166 | +#!/usr/bin/env python |
167 | +# vim: tabstop=4 shiftwidth=4 softtabstop=4 |
168 | + |
169 | +# Copyright 2010 United States Government as represented by the |
170 | +# Administrator of the National Aeronautics and Space Administration. |
171 | +# All Rights Reserved. |
172 | +# |
173 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
174 | +# you may not use this file except in compliance with the License. |
175 | +# You may obtain a copy of the License at |
176 | +# |
177 | +# http://www.apache.org/licenses/LICENSE-2.0 |
178 | +# |
179 | +# Unless required by applicable law or agreed to in writing, software |
180 | +# distributed under the License is distributed on an "AS IS" BASIS, |
181 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
182 | +# See the License for the specific language governing permissions and |
183 | +# limitations under the License. |
184 | + |
185 | +# Colorizer Code is borrowed from Twisted: |
186 | +# Copyright (c) 2001-2010 Twisted Matrix Laboratories. |
187 | +# |
188 | +# Permission is hereby granted, free of charge, to any person obtaining |
189 | +# a copy of this software and associated documentation files (the |
190 | +# "Software"), to deal in the Software without restriction, including |
191 | +# without limitation the rights to use, copy, modify, merge, publish, |
192 | +# distribute, sublicense, and/or sell copies of the Software, and to |
193 | +# permit persons to whom the Software is furnished to do so, subject to |
194 | +# the following conditions: |
195 | +# |
196 | +# The above copyright notice and this permission notice shall be |
197 | +# included in all copies or substantial portions of the Software. |
198 | +# |
199 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
200 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
201 | +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
202 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
203 | +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
204 | +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
205 | +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
206 | +"""Unittest runner for Nova. |
207 | + |
208 | +To run all tests |
209 | + python run_tests.py |
210 | + |
211 | +To run a single test: |
212 | + python run_tests.py test_compute:ComputeTestCase.test_run_terminate |
213 | + |
214 | +To run a single test module: |
215 | + python run_tests.py test_compute |
216 | + |
217 | + or |
218 | + |
219 | + python run_tests.py api.test_wsgi |
220 | + |
221 | +""" |
222 | + |
223 | +import gettext |
224 | +import os |
225 | +import unittest |
226 | +import sys |
227 | + |
228 | +# If ../nova/__init__.py exists, add ../ to Python search path, so that |
229 | +# it will override what happens to be installed in /usr/(local/)lib/python... |
230 | +possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), |
231 | + os.pardir, |
232 | + os.pardir)) |
233 | +if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): |
234 | + sys.path.insert(0, possible_topdir) |
235 | + |
236 | + |
237 | +gettext.install('nova', unicode=1) |
238 | + |
239 | +from nose import config |
240 | +from nose import core |
241 | +from nose import result |
242 | + |
243 | +from smoketests import flags |
244 | +FLAGS = flags.FLAGS |
245 | + |
246 | + |
247 | +class _AnsiColorizer(object): |
248 | + """ |
249 | + A colorizer is an object that loosely wraps around a stream, allowing |
250 | + callers to write text to the stream in a particular color. |
251 | + |
252 | + Colorizer classes must implement C{supported()} and C{write(text, color)}. |
253 | + """ |
254 | + _colors = dict(black=30, red=31, green=32, yellow=33, |
255 | + blue=34, magenta=35, cyan=36, white=37) |
256 | + |
257 | + def __init__(self, stream): |
258 | + self.stream = stream |
259 | + |
260 | + def supported(cls, stream=sys.stdout): |
261 | + """ |
262 | + A class method that returns True if the current platform supports |
263 | + coloring terminal output using this method. Returns False otherwise. |
264 | + """ |
265 | + if not stream.isatty(): |
266 | + return False # auto color only on TTYs |
267 | + try: |
268 | + import curses |
269 | + except ImportError: |
270 | + return False |
271 | + else: |
272 | + try: |
273 | + try: |
274 | + return curses.tigetnum("colors") > 2 |
275 | + except curses.error: |
276 | + curses.setupterm() |
277 | + return curses.tigetnum("colors") > 2 |
278 | + except: |
279 | + raise |
280 | + # guess false in case of error |
281 | + return False |
282 | + supported = classmethod(supported) |
283 | + |
284 | + def write(self, text, color): |
285 | + """ |
286 | + Write the given text to the stream in the given color. |
287 | + |
288 | + @param text: Text to be written to the stream. |
289 | + |
290 | + @param color: A string label for a color. e.g. 'red', 'white'. |
291 | + """ |
292 | + color = self._colors[color] |
293 | + self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text)) |
294 | + |
295 | + |
296 | +class _Win32Colorizer(object): |
297 | + """ |
298 | + See _AnsiColorizer docstring. |
299 | + """ |
300 | + def __init__(self, stream): |
301 | + from win32console import GetStdHandle, STD_OUT_HANDLE, \ |
302 | + FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \ |
303 | + FOREGROUND_INTENSITY |
304 | + red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN, |
305 | + FOREGROUND_BLUE, FOREGROUND_INTENSITY) |
306 | + self.stream = stream |
307 | + self.screenBuffer = GetStdHandle(STD_OUT_HANDLE) |
308 | + self._colors = { |
309 | + 'normal': red | green | blue, |
310 | + 'red': red | bold, |
311 | + 'green': green | bold, |
312 | + 'blue': blue | bold, |
313 | + 'yellow': red | green | bold, |
314 | + 'magenta': red | blue | bold, |
315 | + 'cyan': green | blue | bold, |
316 | + 'white': red | green | blue | bold |
317 | + } |
318 | + |
319 | + def supported(cls, stream=sys.stdout): |
320 | + try: |
321 | + import win32console |
322 | + screenBuffer = win32console.GetStdHandle( |
323 | + win32console.STD_OUT_HANDLE) |
324 | + except ImportError: |
325 | + return False |
326 | + import pywintypes |
327 | + try: |
328 | + screenBuffer.SetConsoleTextAttribute( |
329 | + win32console.FOREGROUND_RED | |
330 | + win32console.FOREGROUND_GREEN | |
331 | + win32console.FOREGROUND_BLUE) |
332 | + except pywintypes.error: |
333 | + return False |
334 | + else: |
335 | + return True |
336 | + supported = classmethod(supported) |
337 | + |
338 | + def write(self, text, color): |
339 | + color = self._colors[color] |
340 | + self.screenBuffer.SetConsoleTextAttribute(color) |
341 | + self.stream.write(text) |
342 | + self.screenBuffer.SetConsoleTextAttribute(self._colors['normal']) |
343 | + |
344 | + |
345 | +class _NullColorizer(object): |
346 | + """ |
347 | + See _AnsiColorizer docstring. |
348 | + """ |
349 | + def __init__(self, stream): |
350 | + self.stream = stream |
351 | + |
352 | + def supported(cls, stream=sys.stdout): |
353 | + return True |
354 | + supported = classmethod(supported) |
355 | + |
356 | + def write(self, text, color): |
357 | + self.stream.write(text) |
358 | + |
359 | + |
360 | +class NovaTestResult(result.TextTestResult): |
361 | + def __init__(self, *args, **kw): |
362 | + result.TextTestResult.__init__(self, *args, **kw) |
363 | + self._last_case = None |
364 | + self.colorizer = None |
365 | + # NOTE(vish): reset stdout for the terminal check |
366 | + stdout = sys.stdout |
367 | + sys.stdout = sys.__stdout__ |
368 | + for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]: |
369 | + if colorizer.supported(): |
370 | + self.colorizer = colorizer(self.stream) |
371 | + break |
372 | + sys.stdout = stdout |
373 | + |
374 | + def getDescription(self, test): |
375 | + return str(test) |
376 | + |
377 | + # NOTE(vish): copied from unittest with edit to add color |
378 | + def addSuccess(self, test): |
379 | + unittest.TestResult.addSuccess(self, test) |
380 | + if self.showAll: |
381 | + self.colorizer.write("OK", 'green') |
382 | + self.stream.writeln() |
383 | + elif self.dots: |
384 | + self.stream.write('.') |
385 | + self.stream.flush() |
386 | + |
387 | + # NOTE(vish): copied from unittest with edit to add color |
388 | + def addFailure(self, test, err): |
389 | + unittest.TestResult.addFailure(self, test, err) |
390 | + if self.showAll: |
391 | + self.colorizer.write("FAIL", 'red') |
392 | + self.stream.writeln() |
393 | + elif self.dots: |
394 | + self.stream.write('F') |
395 | + self.stream.flush() |
396 | + |
397 | + # NOTE(vish): copied from nose with edit to add color |
398 | + def addError(self, test, err): |
399 | + """Overrides normal addError to add support for |
400 | + errorClasses. If the exception is a registered class, the |
401 | + error will be added to the list for that class, not errors. |
402 | + """ |
403 | + stream = getattr(self, 'stream', None) |
404 | + ec, ev, tb = err |
405 | + try: |
406 | + exc_info = self._exc_info_to_string(err, test) |
407 | + except TypeError: |
408 | + # 2.3 compat |
409 | + exc_info = self._exc_info_to_string(err) |
410 | + for cls, (storage, label, isfail) in self.errorClasses.items(): |
411 | + if result.isclass(ec) and issubclass(ec, cls): |
412 | + if isfail: |
413 | + test.passed = False |
414 | + storage.append((test, exc_info)) |
415 | + # Might get patched into a streamless result |
416 | + if stream is not None: |
417 | + if self.showAll: |
418 | + message = [label] |
419 | + detail = result._exception_detail(err[1]) |
420 | + if detail: |
421 | + message.append(detail) |
422 | + stream.writeln(": ".join(message)) |
423 | + elif self.dots: |
424 | + stream.write(label[:1]) |
425 | + return |
426 | + self.errors.append((test, exc_info)) |
427 | + test.passed = False |
428 | + if stream is not None: |
429 | + if self.showAll: |
430 | + self.colorizer.write("ERROR", 'red') |
431 | + self.stream.writeln() |
432 | + elif self.dots: |
433 | + stream.write('E') |
434 | + |
435 | + def startTest(self, test): |
436 | + unittest.TestResult.startTest(self, test) |
437 | + current_case = test.test.__class__.__name__ |
438 | + |
439 | + if self.showAll: |
440 | + if current_case != self._last_case: |
441 | + self.stream.writeln(current_case) |
442 | + self._last_case = current_case |
443 | + |
444 | + self.stream.write( |
445 | + ' %s' % str(test.test._testMethodName).ljust(60)) |
446 | + self.stream.flush() |
447 | + |
448 | + |
449 | +class NovaTestRunner(core.TextTestRunner): |
450 | + def _makeResult(self): |
451 | + return NovaTestResult(self.stream, |
452 | + self.descriptions, |
453 | + self.verbosity, |
454 | + self.config) |
455 | + |
456 | + |
457 | +if __name__ == '__main__': |
458 | + if not os.getenv('EC2_ACCESS_KEY'): |
459 | + print _('Missing EC2 environment variables. Please ' \ |
460 | + 'source the appropriate novarc file before ' \ |
461 | + 'running this test.') |
462 | + sys.exit(1) |
463 | + |
464 | + argv = FLAGS(sys.argv) |
465 | + testdir = os.path.abspath("./") |
466 | + c = config.Config(stream=sys.stdout, |
467 | + env=os.environ, |
468 | + verbosity=3, |
469 | + workingDir=testdir, |
470 | + plugins=core.DefaultPluginManager()) |
471 | + |
472 | + runner = NovaTestRunner(stream=c.stream, |
473 | + verbosity=c.verbosity, |
474 | + config=c) |
475 | + sys.exit(not core.run(config=c, testRunner=runner, argv=argv)) |
476 | |
477 | === renamed file 'smoketests/admin_smoketests.py' => 'smoketests/test_admin.py' |
478 | --- smoketests/admin_smoketests.py 2011-01-12 08:47:54 +0000 |
479 | +++ smoketests/test_admin.py 2011-03-20 19:08:31 +0000 |
480 | @@ -35,10 +35,7 @@ |
481 | from smoketests import base |
482 | |
483 | |
484 | -SUITE_NAMES = '[user]' |
485 | - |
486 | FLAGS = flags.FLAGS |
487 | -flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES) |
488 | |
489 | # TODO(devamcar): Use random tempfile |
490 | ZIP_FILENAME = '/tmp/nova-me-x509.zip' |
491 | @@ -92,7 +89,3 @@ |
492 | os.remove(ZIP_FILENAME) |
493 | except: |
494 | pass |
495 | - |
496 | -if __name__ == "__main__": |
497 | - suites = {'user': unittest.makeSuite(UserTests)} |
498 | - sys.exit(base.run_tests(suites)) |
499 | |
500 | === renamed file 'smoketests/netadmin_smoketests.py' => 'smoketests/test_netadmin.py' |
501 | --- smoketests/netadmin_smoketests.py 2011-02-23 02:04:32 +0000 |
502 | +++ smoketests/test_netadmin.py 2011-03-20 19:08:31 +0000 |
503 | @@ -21,7 +21,6 @@ |
504 | import random |
505 | import sys |
506 | import time |
507 | -import unittest |
508 | |
509 | # If ../nova/__init__.py exists, add ../ to Python search path, so that |
510 | # it will override what happens to be installed in /usr/(local/)lib/python... |
511 | @@ -74,8 +73,10 @@ |
512 | groups = self.conn.get_all_security_groups(['default']) |
513 | for rule in groups[0].rules: |
514 | if (rule.ip_protocol == 'tcp' and |
515 | - rule.from_port <= 22 and rule.to_port >= 22): |
516 | + int(rule.from_port) <= 22 and |
517 | + int(rule.to_port) >= 22): |
518 | ssh_authorized = True |
519 | + break |
520 | if not ssh_authorized: |
521 | self.conn.authorize_security_group('default', |
522 | ip_protocol='tcp', |
523 | @@ -137,11 +138,6 @@ |
524 | if not self.wait_for_running(self.data['instance']): |
525 | self.fail('instance failed to start') |
526 | self.data['instance'].update() |
527 | - if not self.wait_for_ping(self.data['instance'].private_dns_name): |
528 | - self.fail('could not ping instance') |
529 | - if not self.wait_for_ssh(self.data['instance'].private_dns_name, |
530 | - TEST_KEY): |
531 | - self.fail('could not ssh to instance') |
532 | |
533 | def test_003_can_authorize_security_group_ingress(self): |
534 | self.assertTrue(self.conn.authorize_security_group(TEST_GROUP, |
535 | @@ -185,10 +181,3 @@ |
536 | self.assertFalse(TEST_GROUP in [group.name for group in groups]) |
537 | self.conn.terminate_instances([self.data['instance'].id]) |
538 | self.assertTrue(self.conn.release_address(self.data['public_ip'])) |
539 | - |
540 | - |
541 | -if __name__ == "__main__": |
542 | - suites = {'address': unittest.makeSuite(AddressTests), |
543 | - 'security_group': unittest.makeSuite(SecurityGroupTests) |
544 | - } |
545 | - sys.exit(base.run_tests(suites)) |
546 | |
547 | === renamed file 'smoketests/sysadmin_smoketests.py' => 'smoketests/test_sysadmin.py' |
548 | --- smoketests/sysadmin_smoketests.py 2011-03-18 01:54:51 +0000 |
549 | +++ smoketests/test_sysadmin.py 2011-03-20 19:08:31 +0000 |
550 | @@ -16,12 +16,12 @@ |
551 | # License for the specific language governing permissions and limitations |
552 | # under the License. |
553 | |
554 | -import commands |
555 | import os |
556 | import random |
557 | import sys |
558 | import time |
559 | -import unittest |
560 | +import tempfile |
561 | +import shutil |
562 | |
563 | # If ../nova/__init__.py exists, add ../ to Python search path, so that |
564 | # it will override what happens to be installed in /usr/(local/)lib/python... |
565 | @@ -48,10 +48,18 @@ |
566 | |
567 | class ImageTests(base.UserSmokeTestCase): |
568 | def test_001_can_bundle_image(self): |
569 | - self.assertTrue(self.bundle_image(FLAGS.bundle_image)) |
570 | + self.data['tempdir'] = tempfile.mkdtemp() |
571 | + self.assertTrue(self.bundle_image(FLAGS.bundle_image, |
572 | + self.data['tempdir'])) |
573 | |
574 | def test_002_can_upload_image(self): |
575 | - self.assertTrue(self.upload_image(TEST_BUCKET, FLAGS.bundle_image)) |
576 | + try: |
577 | + self.assertTrue(self.upload_image(TEST_BUCKET, |
578 | + FLAGS.bundle_image, |
579 | + self.data['tempdir'])) |
580 | + finally: |
581 | + if os.path.exists(self.data['tempdir']): |
582 | + shutil.rmtree(self.data['tempdir']) |
583 | |
584 | def test_003_can_register_image(self): |
585 | image_id = self.conn.register_image('%s/%s.manifest.xml' % |
586 | @@ -192,7 +200,7 @@ |
587 | self.assertEqual(volume.size, 1) |
588 | self.data['volume'] = volume |
589 | # Give network time to find volume. |
590 | - time.sleep(10) |
591 | + time.sleep(5) |
592 | |
593 | def test_002_can_attach_volume(self): |
594 | volume = self.data['volume'] |
595 | @@ -205,6 +213,8 @@ |
596 | else: |
597 | self.fail('cannot attach volume with state %s' % volume.status) |
598 | |
599 | + # Give volume some time to be ready. |
600 | + time.sleep(5) |
601 | volume.attach(self.data['instance'].id, self.device) |
602 | |
603 | # wait |
604 | @@ -219,7 +229,7 @@ |
605 | self.assertTrue(volume.status.startswith('in-use')) |
606 | |
607 | # Give instance time to recognize volume. |
608 | - time.sleep(10) |
609 | + time.sleep(5) |
610 | |
611 | def test_003_can_mount_volume(self): |
612 | ip = self.data['instance'].private_dns_name |
613 | @@ -256,12 +266,13 @@ |
614 | ip = self.data['instance'].private_dns_name |
615 | conn = self.connect_ssh(ip, TEST_KEY) |
616 | stdin, stdout, stderr = conn.exec_command( |
617 | - "df -h | grep %s | awk {'print $2'}" % self.device) |
618 | - out = stdout.read() |
619 | + "blockdev --getsize64 %s" % self.device) |
620 | + out = stdout.read().strip() |
621 | conn.close() |
622 | - if not out.strip() == '1007.9M': |
623 | - self.fail('Volume is not the right size: %s %s' % |
624 | - (out, stderr.read())) |
625 | + expected_size = 1024 * 1024 * 1024 |
626 | + self.assertEquals('%s' % (expected_size,), out, |
627 | + 'Volume is not the right size: %s %s. Expected: %s' % |
628 | + (out, stderr.read(), expected_size)) |
629 | |
630 | def test_006_me_can_umount_volume(self): |
631 | ip = self.data['instance'].private_dns_name |
632 | @@ -284,9 +295,3 @@ |
633 | def test_999_tearDown(self): |
634 | self.conn.terminate_instances([self.data['instance'].id]) |
635 | self.conn.delete_key_pair(TEST_KEY) |
636 | - |
637 | -if __name__ == "__main__": |
638 | - suites = {'image': unittest.makeSuite(ImageTests), |
639 | - 'instance': unittest.makeSuite(InstanceTests), |
640 | - 'volume': unittest.makeSuite(VolumeTests)} |
641 | - sys.exit(base.run_tests(suites)) |
lgtm. Nice fixes