Merge lp:~soren/nova/improve-smoketests into lp:~hudson-openstack/nova/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
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
Vish Ishaya (vishvananda) wrote :

lgtm. Nice fixes

review: Approve
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/test_sysadmin.py

lp:~soren/nova/improve-smoketests updated
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
=== modified file 'nova/tests/api/openstack/test_servers.py'
--- nova/tests/api/openstack/test_servers.py 2011-03-17 22:24:08 +0000
+++ nova/tests/api/openstack/test_servers.py 2011-03-20 19:08:31 +0000
@@ -1174,7 +1174,3 @@
1174 server = dom.childNodes[0]1174 server = dom.childNodes[0]
1175 self.assertEquals(server.nodeName, 'server')1175 self.assertEquals(server.nodeName, 'server')
1176 self.assertTrue(server.getAttribute('adminPass').startswith('fake'))1176 self.assertTrue(server.getAttribute('adminPass').startswith('fake'))
1177
1178
1179if __name__ == "__main__":
1180 unittest.main()
11811177
=== modified file 'run_tests.py'
--- run_tests.py 2011-02-25 01:04:25 +0000
+++ run_tests.py 2011-03-20 19:08:31 +0000
@@ -60,6 +60,8 @@
60import unittest60import unittest
61import sys61import sys
6262
63gettext.install('nova', unicode=1)
64
63from nose import config65from nose import config
64from nose import core66from nose import core
65from nose import result67from nose import result
6668
=== modified file 'smoketests/base.py'
--- smoketests/base.py 2011-02-23 02:04:08 +0000
+++ smoketests/base.py 2011-03-20 19:08:31 +0000
@@ -31,17 +31,24 @@
31SUITE_NAMES = '[image, instance, volume]'31SUITE_NAMES = '[image, instance, volume]'
32FLAGS = flags.FLAGS32FLAGS = flags.FLAGS
33flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES)33flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES)
34flags.DEFINE_integer('ssh_tries', 3, 'Numer of times to try ssh')
34boto_v6 = None35boto_v6 = None
3536
3637
37class SmokeTestCase(unittest.TestCase):38class SmokeTestCase(unittest.TestCase):
38 def connect_ssh(self, ip, key_name):39 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)40 key = paramiko.RSAKey.from_private_key_file('/tmp/%s.pem' % key_name)
41 client = paramiko.SSHClient()41 tries = 0
42 client.set_missing_host_key_policy(paramiko.WarningPolicy())42 while(True):
43 client.connect(ip, username='root', pkey=key)43 try:
44 return client44 client = paramiko.SSHClient()
45 client.set_missing_host_key_policy(paramiko.WarningPolicy())
46 client.connect(ip, username='root', pkey=key, timeout=5)
47 return client
48 except (paramiko.AuthenticationException, paramiko.SSHException):
49 tries += 1
50 if tries == FLAGS.ssh_tries:
51 raise
4552
46 def can_ping(self, ip, command="ping"):53 def can_ping(self, ip, command="ping"):
47 """Attempt to ping the specified IP, and give up after 1 second."""54 """Attempt to ping the specified IP, and give up after 1 second."""
@@ -147,8 +154,8 @@
147 except:154 except:
148 pass155 pass
149156
150 def bundle_image(self, image, kernel=False):157 def bundle_image(self, image, tempdir='/tmp', kernel=False):
151 cmd = 'euca-bundle-image -i %s' % image158 cmd = 'euca-bundle-image -i %s -d %s' % (image, tempdir)
152 if kernel:159 if kernel:
153 cmd += ' --kernel true'160 cmd += ' --kernel true'
154 status, output = commands.getstatusoutput(cmd)161 status, output = commands.getstatusoutput(cmd)
@@ -157,9 +164,9 @@
157 raise Exception(output)164 raise Exception(output)
158 return True165 return True
159166
160 def upload_image(self, bucket_name, image):167 def upload_image(self, bucket_name, image, tempdir='/tmp'):
161 cmd = 'euca-upload-bundle -b '168 cmd = 'euca-upload-bundle -b '
162 cmd += '%s -m /tmp/%s.manifest.xml' % (bucket_name, image)169 cmd += '%s -m %s/%s.manifest.xml' % (bucket_name, tempdir, image)
163 status, output = commands.getstatusoutput(cmd)170 status, output = commands.getstatusoutput(cmd)
164 if status != 0:171 if status != 0:
165 print '%s -> \n %s' % (cmd, output)172 print '%s -> \n %s' % (cmd, output)
@@ -183,29 +190,3 @@
183 global TEST_DATA190 global TEST_DATA
184 self.conn = self.connection_for_env()191 self.conn = self.connection_for_env()
185 self.data = TEST_DATA192 self.data = TEST_DATA
186
187
188def run_tests(suites):
189 argv = FLAGS(sys.argv)
190 if FLAGS.use_ipv6:
191 global boto_v6
192 boto_v6 = __import__('boto_v6')
193
194 if not os.getenv('EC2_ACCESS_KEY'):
195 print >> sys.stderr, 'Missing EC2 environment variables. Please ' \
196 'source the appropriate novarc file before ' \
197 'running this test.'
198 return 1
199
200 if FLAGS.suite:
201 try:
202 suite = suites[FLAGS.suite]
203 except KeyError:
204 print >> sys.stderr, 'Available test suites:', \
205 ', '.join(suites.keys())
206 return 1
207
208 unittest.TextTestRunner(verbosity=2).run(suite)
209 else:
210 for suite in suites.itervalues():
211 unittest.TextTestRunner(verbosity=2).run(suite)
212193
=== modified file 'smoketests/proxy.sh'
--- smoketests/proxy.sh 2011-02-23 02:04:32 +0000
+++ smoketests/proxy.sh 2011-03-20 19:08:31 +0000
@@ -11,12 +11,19 @@
11mkfifo backpipe111mkfifo backpipe1
12mkfifo backpipe212mkfifo backpipe2
1313
14if nc -h 2>&1 | grep -i openbsd
15then
16 NC_LISTEN="nc -l"
17else
18 NC_LISTEN="nc -l -p"
19fi
20
14# NOTE(vish): proxy metadata on port 8021# NOTE(vish): proxy metadata on port 80
15while true; do22while true; do
16 nc -l -p 80 0<backpipe1 | nc 169.254.169.254 80 1>backpipe123 $NC_LISTEN 80 0<backpipe1 | nc 169.254.169.254 80 1>backpipe1
17done &24done &
1825
19# NOTE(vish): proxy google on port 808026# NOTE(vish): proxy google on port 8080
20while true; do27while true; do
21 nc -l -p 8080 0<backpipe2 | nc 74.125.19.99 80 1>backpipe228 $NC_LISTEN 8080 0<backpipe2 | nc 74.125.19.99 80 1>backpipe2
22done &29done &
2330
=== modified file 'smoketests/public_network_smoketests.py'
--- smoketests/public_network_smoketests.py 2011-02-23 02:04:08 +0000
+++ smoketests/public_network_smoketests.py 2011-03-20 19:08:31 +0000
@@ -19,10 +19,8 @@
19import commands19import commands
20import os20import os
21import random21import random
22import socket
23import sys22import sys
24import time23import time
25import unittest
2624
27# If ../nova/__init__.py exists, add ../ to Python search path, so that25# If ../nova/__init__.py exists, add ../ to Python search path, so that
28# it will override what happens to be installed in /usr/(local/)lib/python...26# it will override what happens to be installed in /usr/(local/)lib/python...
@@ -181,7 +179,3 @@
181 self.conn.delete_security_group(security_group_name)179 self.conn.delete_security_group(security_group_name)
182 if 'instance_id' in self.data:180 if 'instance_id' in self.data:
183 self.conn.terminate_instances([self.data['instance_id']])181 self.conn.terminate_instances([self.data['instance_id']])
184
185if __name__ == "__main__":
186 suites = {'instance': unittest.makeSuite(InstanceTestsFromPublic)}
187 sys.exit(base.run_tests(suites))
188182
=== added file 'smoketests/run_tests.py'
--- smoketests/run_tests.py 1970-01-01 00:00:00 +0000
+++ smoketests/run_tests.py 2011-03-20 19:08:31 +0000
@@ -0,0 +1,310 @@
1#!/usr/bin/env python
2# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
4# Copyright 2010 United States Government as represented by the
5# Administrator of the National Aeronautics and Space Administration.
6# All Rights Reserved.
7#
8# Licensed under the Apache License, Version 2.0 (the "License");
9# you may not use this file except in compliance with the License.
10# You may obtain a copy of the License at
11#
12# http://www.apache.org/licenses/LICENSE-2.0
13#
14# Unless required by applicable law or agreed to in writing, software
15# distributed under the License is distributed on an "AS IS" BASIS,
16# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17# See the License for the specific language governing permissions and
18# limitations under the License.
19
20# Colorizer Code is borrowed from Twisted:
21# Copyright (c) 2001-2010 Twisted Matrix Laboratories.
22#
23# Permission is hereby granted, free of charge, to any person obtaining
24# a copy of this software and associated documentation files (the
25# "Software"), to deal in the Software without restriction, including
26# without limitation the rights to use, copy, modify, merge, publish,
27# distribute, sublicense, and/or sell copies of the Software, and to
28# permit persons to whom the Software is furnished to do so, subject to
29# the following conditions:
30#
31# The above copyright notice and this permission notice shall be
32# included in all copies or substantial portions of the Software.
33#
34# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41"""Unittest runner for Nova.
42
43To run all tests
44 python run_tests.py
45
46To run a single test:
47 python run_tests.py test_compute:ComputeTestCase.test_run_terminate
48
49To run a single test module:
50 python run_tests.py test_compute
51
52 or
53
54 python run_tests.py api.test_wsgi
55
56"""
57
58import gettext
59import os
60import unittest
61import sys
62
63# If ../nova/__init__.py exists, add ../ to Python search path, so that
64# it will override what happens to be installed in /usr/(local/)lib/python...
65possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
66 os.pardir,
67 os.pardir))
68if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')):
69 sys.path.insert(0, possible_topdir)
70
71
72gettext.install('nova', unicode=1)
73
74from nose import config
75from nose import core
76from nose import result
77
78from smoketests import flags
79FLAGS = flags.FLAGS
80
81
82class _AnsiColorizer(object):
83 """
84 A colorizer is an object that loosely wraps around a stream, allowing
85 callers to write text to the stream in a particular color.
86
87 Colorizer classes must implement C{supported()} and C{write(text, color)}.
88 """
89 _colors = dict(black=30, red=31, green=32, yellow=33,
90 blue=34, magenta=35, cyan=36, white=37)
91
92 def __init__(self, stream):
93 self.stream = stream
94
95 def supported(cls, stream=sys.stdout):
96 """
97 A class method that returns True if the current platform supports
98 coloring terminal output using this method. Returns False otherwise.
99 """
100 if not stream.isatty():
101 return False # auto color only on TTYs
102 try:
103 import curses
104 except ImportError:
105 return False
106 else:
107 try:
108 try:
109 return curses.tigetnum("colors") > 2
110 except curses.error:
111 curses.setupterm()
112 return curses.tigetnum("colors") > 2
113 except:
114 raise
115 # guess false in case of error
116 return False
117 supported = classmethod(supported)
118
119 def write(self, text, color):
120 """
121 Write the given text to the stream in the given color.
122
123 @param text: Text to be written to the stream.
124
125 @param color: A string label for a color. e.g. 'red', 'white'.
126 """
127 color = self._colors[color]
128 self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
129
130
131class _Win32Colorizer(object):
132 """
133 See _AnsiColorizer docstring.
134 """
135 def __init__(self, stream):
136 from win32console import GetStdHandle, STD_OUT_HANDLE, \
137 FOREGROUND_RED, FOREGROUND_BLUE, FOREGROUND_GREEN, \
138 FOREGROUND_INTENSITY
139 red, green, blue, bold = (FOREGROUND_RED, FOREGROUND_GREEN,
140 FOREGROUND_BLUE, FOREGROUND_INTENSITY)
141 self.stream = stream
142 self.screenBuffer = GetStdHandle(STD_OUT_HANDLE)
143 self._colors = {
144 'normal': red | green | blue,
145 'red': red | bold,
146 'green': green | bold,
147 'blue': blue | bold,
148 'yellow': red | green | bold,
149 'magenta': red | blue | bold,
150 'cyan': green | blue | bold,
151 'white': red | green | blue | bold
152 }
153
154 def supported(cls, stream=sys.stdout):
155 try:
156 import win32console
157 screenBuffer = win32console.GetStdHandle(
158 win32console.STD_OUT_HANDLE)
159 except ImportError:
160 return False
161 import pywintypes
162 try:
163 screenBuffer.SetConsoleTextAttribute(
164 win32console.FOREGROUND_RED |
165 win32console.FOREGROUND_GREEN |
166 win32console.FOREGROUND_BLUE)
167 except pywintypes.error:
168 return False
169 else:
170 return True
171 supported = classmethod(supported)
172
173 def write(self, text, color):
174 color = self._colors[color]
175 self.screenBuffer.SetConsoleTextAttribute(color)
176 self.stream.write(text)
177 self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
178
179
180class _NullColorizer(object):
181 """
182 See _AnsiColorizer docstring.
183 """
184 def __init__(self, stream):
185 self.stream = stream
186
187 def supported(cls, stream=sys.stdout):
188 return True
189 supported = classmethod(supported)
190
191 def write(self, text, color):
192 self.stream.write(text)
193
194
195class NovaTestResult(result.TextTestResult):
196 def __init__(self, *args, **kw):
197 result.TextTestResult.__init__(self, *args, **kw)
198 self._last_case = None
199 self.colorizer = None
200 # NOTE(vish): reset stdout for the terminal check
201 stdout = sys.stdout
202 sys.stdout = sys.__stdout__
203 for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
204 if colorizer.supported():
205 self.colorizer = colorizer(self.stream)
206 break
207 sys.stdout = stdout
208
209 def getDescription(self, test):
210 return str(test)
211
212 # NOTE(vish): copied from unittest with edit to add color
213 def addSuccess(self, test):
214 unittest.TestResult.addSuccess(self, test)
215 if self.showAll:
216 self.colorizer.write("OK", 'green')
217 self.stream.writeln()
218 elif self.dots:
219 self.stream.write('.')
220 self.stream.flush()
221
222 # NOTE(vish): copied from unittest with edit to add color
223 def addFailure(self, test, err):
224 unittest.TestResult.addFailure(self, test, err)
225 if self.showAll:
226 self.colorizer.write("FAIL", 'red')
227 self.stream.writeln()
228 elif self.dots:
229 self.stream.write('F')
230 self.stream.flush()
231
232 # NOTE(vish): copied from nose with edit to add color
233 def addError(self, test, err):
234 """Overrides normal addError to add support for
235 errorClasses. If the exception is a registered class, the
236 error will be added to the list for that class, not errors.
237 """
238 stream = getattr(self, 'stream', None)
239 ec, ev, tb = err
240 try:
241 exc_info = self._exc_info_to_string(err, test)
242 except TypeError:
243 # 2.3 compat
244 exc_info = self._exc_info_to_string(err)
245 for cls, (storage, label, isfail) in self.errorClasses.items():
246 if result.isclass(ec) and issubclass(ec, cls):
247 if isfail:
248 test.passed = False
249 storage.append((test, exc_info))
250 # Might get patched into a streamless result
251 if stream is not None:
252 if self.showAll:
253 message = [label]
254 detail = result._exception_detail(err[1])
255 if detail:
256 message.append(detail)
257 stream.writeln(": ".join(message))
258 elif self.dots:
259 stream.write(label[:1])
260 return
261 self.errors.append((test, exc_info))
262 test.passed = False
263 if stream is not None:
264 if self.showAll:
265 self.colorizer.write("ERROR", 'red')
266 self.stream.writeln()
267 elif self.dots:
268 stream.write('E')
269
270 def startTest(self, test):
271 unittest.TestResult.startTest(self, test)
272 current_case = test.test.__class__.__name__
273
274 if self.showAll:
275 if current_case != self._last_case:
276 self.stream.writeln(current_case)
277 self._last_case = current_case
278
279 self.stream.write(
280 ' %s' % str(test.test._testMethodName).ljust(60))
281 self.stream.flush()
282
283
284class NovaTestRunner(core.TextTestRunner):
285 def _makeResult(self):
286 return NovaTestResult(self.stream,
287 self.descriptions,
288 self.verbosity,
289 self.config)
290
291
292if __name__ == '__main__':
293 if not os.getenv('EC2_ACCESS_KEY'):
294 print _('Missing EC2 environment variables. Please ' \
295 'source the appropriate novarc file before ' \
296 'running this test.')
297 sys.exit(1)
298
299 argv = FLAGS(sys.argv)
300 testdir = os.path.abspath("./")
301 c = config.Config(stream=sys.stdout,
302 env=os.environ,
303 verbosity=3,
304 workingDir=testdir,
305 plugins=core.DefaultPluginManager())
306
307 runner = NovaTestRunner(stream=c.stream,
308 verbosity=c.verbosity,
309 config=c)
310 sys.exit(not core.run(config=c, testRunner=runner, argv=argv))
0311
=== renamed file 'smoketests/admin_smoketests.py' => 'smoketests/test_admin.py'
--- smoketests/admin_smoketests.py 2011-01-12 08:47:54 +0000
+++ smoketests/test_admin.py 2011-03-20 19:08:31 +0000
@@ -35,10 +35,7 @@
35from smoketests import base35from smoketests import base
3636
3737
38SUITE_NAMES = '[user]'
39
40FLAGS = flags.FLAGS38FLAGS = flags.FLAGS
41flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES)
4239
43# TODO(devamcar): Use random tempfile40# TODO(devamcar): Use random tempfile
44ZIP_FILENAME = '/tmp/nova-me-x509.zip'41ZIP_FILENAME = '/tmp/nova-me-x509.zip'
@@ -92,7 +89,3 @@
92 os.remove(ZIP_FILENAME)89 os.remove(ZIP_FILENAME)
93 except:90 except:
94 pass91 pass
95
96if __name__ == "__main__":
97 suites = {'user': unittest.makeSuite(UserTests)}
98 sys.exit(base.run_tests(suites))
9992
=== renamed file 'smoketests/netadmin_smoketests.py' => 'smoketests/test_netadmin.py'
--- smoketests/netadmin_smoketests.py 2011-02-23 02:04:32 +0000
+++ smoketests/test_netadmin.py 2011-03-20 19:08:31 +0000
@@ -21,7 +21,6 @@
21import random21import random
22import sys22import sys
23import time23import time
24import unittest
2524
26# If ../nova/__init__.py exists, add ../ to Python search path, so that25# If ../nova/__init__.py exists, add ../ to Python search path, so that
27# it will override what happens to be installed in /usr/(local/)lib/python...26# it will override what happens to be installed in /usr/(local/)lib/python...
@@ -74,8 +73,10 @@
74 groups = self.conn.get_all_security_groups(['default'])73 groups = self.conn.get_all_security_groups(['default'])
75 for rule in groups[0].rules:74 for rule in groups[0].rules:
76 if (rule.ip_protocol == 'tcp' and75 if (rule.ip_protocol == 'tcp' and
77 rule.from_port <= 22 and rule.to_port >= 22):76 int(rule.from_port) <= 22 and
77 int(rule.to_port) >= 22):
78 ssh_authorized = True78 ssh_authorized = True
79 break
79 if not ssh_authorized:80 if not ssh_authorized:
80 self.conn.authorize_security_group('default',81 self.conn.authorize_security_group('default',
81 ip_protocol='tcp',82 ip_protocol='tcp',
@@ -137,11 +138,6 @@
137 if not self.wait_for_running(self.data['instance']):138 if not self.wait_for_running(self.data['instance']):
138 self.fail('instance failed to start')139 self.fail('instance failed to start')
139 self.data['instance'].update()140 self.data['instance'].update()
140 if not self.wait_for_ping(self.data['instance'].private_dns_name):
141 self.fail('could not ping instance')
142 if not self.wait_for_ssh(self.data['instance'].private_dns_name,
143 TEST_KEY):
144 self.fail('could not ssh to instance')
145141
146 def test_003_can_authorize_security_group_ingress(self):142 def test_003_can_authorize_security_group_ingress(self):
147 self.assertTrue(self.conn.authorize_security_group(TEST_GROUP,143 self.assertTrue(self.conn.authorize_security_group(TEST_GROUP,
@@ -185,10 +181,3 @@
185 self.assertFalse(TEST_GROUP in [group.name for group in groups])181 self.assertFalse(TEST_GROUP in [group.name for group in groups])
186 self.conn.terminate_instances([self.data['instance'].id])182 self.conn.terminate_instances([self.data['instance'].id])
187 self.assertTrue(self.conn.release_address(self.data['public_ip']))183 self.assertTrue(self.conn.release_address(self.data['public_ip']))
188
189
190if __name__ == "__main__":
191 suites = {'address': unittest.makeSuite(AddressTests),
192 'security_group': unittest.makeSuite(SecurityGroupTests)
193 }
194 sys.exit(base.run_tests(suites))
195184
=== renamed file 'smoketests/sysadmin_smoketests.py' => 'smoketests/test_sysadmin.py'
--- smoketests/sysadmin_smoketests.py 2011-03-18 01:54:51 +0000
+++ smoketests/test_sysadmin.py 2011-03-20 19:08:31 +0000
@@ -16,12 +16,12 @@
16# License for the specific language governing permissions and limitations16# License for the specific language governing permissions and limitations
17# under the License.17# under the License.
1818
19import commands
20import os19import os
21import random20import random
22import sys21import sys
23import time22import time
24import unittest23import tempfile
24import shutil
2525
26# If ../nova/__init__.py exists, add ../ to Python search path, so that26# If ../nova/__init__.py exists, add ../ to Python search path, so that
27# it will override what happens to be installed in /usr/(local/)lib/python...27# it will override what happens to be installed in /usr/(local/)lib/python...
@@ -48,10 +48,18 @@
4848
49class ImageTests(base.UserSmokeTestCase):49class ImageTests(base.UserSmokeTestCase):
50 def test_001_can_bundle_image(self):50 def test_001_can_bundle_image(self):
51 self.assertTrue(self.bundle_image(FLAGS.bundle_image))51 self.data['tempdir'] = tempfile.mkdtemp()
52 self.assertTrue(self.bundle_image(FLAGS.bundle_image,
53 self.data['tempdir']))
5254
53 def test_002_can_upload_image(self):55 def test_002_can_upload_image(self):
54 self.assertTrue(self.upload_image(TEST_BUCKET, FLAGS.bundle_image))56 try:
57 self.assertTrue(self.upload_image(TEST_BUCKET,
58 FLAGS.bundle_image,
59 self.data['tempdir']))
60 finally:
61 if os.path.exists(self.data['tempdir']):
62 shutil.rmtree(self.data['tempdir'])
5563
56 def test_003_can_register_image(self):64 def test_003_can_register_image(self):
57 image_id = self.conn.register_image('%s/%s.manifest.xml' %65 image_id = self.conn.register_image('%s/%s.manifest.xml' %
@@ -192,7 +200,7 @@
192 self.assertEqual(volume.size, 1)200 self.assertEqual(volume.size, 1)
193 self.data['volume'] = volume201 self.data['volume'] = volume
194 # Give network time to find volume.202 # Give network time to find volume.
195 time.sleep(10)203 time.sleep(5)
196204
197 def test_002_can_attach_volume(self):205 def test_002_can_attach_volume(self):
198 volume = self.data['volume']206 volume = self.data['volume']
@@ -205,6 +213,8 @@
205 else:213 else:
206 self.fail('cannot attach volume with state %s' % volume.status)214 self.fail('cannot attach volume with state %s' % volume.status)
207215
216 # Give volume some time to be ready.
217 time.sleep(5)
208 volume.attach(self.data['instance'].id, self.device)218 volume.attach(self.data['instance'].id, self.device)
209219
210 # wait220 # wait
@@ -219,7 +229,7 @@
219 self.assertTrue(volume.status.startswith('in-use'))229 self.assertTrue(volume.status.startswith('in-use'))
220230
221 # Give instance time to recognize volume.231 # Give instance time to recognize volume.
222 time.sleep(10)232 time.sleep(5)
223233
224 def test_003_can_mount_volume(self):234 def test_003_can_mount_volume(self):
225 ip = self.data['instance'].private_dns_name235 ip = self.data['instance'].private_dns_name
@@ -256,12 +266,13 @@
256 ip = self.data['instance'].private_dns_name266 ip = self.data['instance'].private_dns_name
257 conn = self.connect_ssh(ip, TEST_KEY)267 conn = self.connect_ssh(ip, TEST_KEY)
258 stdin, stdout, stderr = conn.exec_command(268 stdin, stdout, stderr = conn.exec_command(
259 "df -h | grep %s | awk {'print $2'}" % self.device)269 "blockdev --getsize64 %s" % self.device)
260 out = stdout.read()270 out = stdout.read().strip()
261 conn.close()271 conn.close()
262 if not out.strip() == '1007.9M':272 expected_size = 1024 * 1024 * 1024
263 self.fail('Volume is not the right size: %s %s' %273 self.assertEquals('%s' % (expected_size,), out,
264 (out, stderr.read()))274 'Volume is not the right size: %s %s. Expected: %s' %
275 (out, stderr.read(), expected_size))
265276
266 def test_006_me_can_umount_volume(self):277 def test_006_me_can_umount_volume(self):
267 ip = self.data['instance'].private_dns_name278 ip = self.data['instance'].private_dns_name
@@ -284,9 +295,3 @@
284 def test_999_tearDown(self):295 def test_999_tearDown(self):
285 self.conn.terminate_instances([self.data['instance'].id])296 self.conn.terminate_instances([self.data['instance'].id])
286 self.conn.delete_key_pair(TEST_KEY)297 self.conn.delete_key_pair(TEST_KEY)
287
288if __name__ == "__main__":
289 suites = {'image': unittest.makeSuite(ImageTests),
290 'instance': unittest.makeSuite(InstanceTests),
291 'volume': unittest.makeSuite(VolumeTests)}
292 sys.exit(base.run_tests(suites))