Merge lp:~anso/nova/smoketests_fixes into lp:~hudson-openstack/nova/trunk
- smoketests_fixes
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Vish Ishaya |
Approved revision: | 529 |
Merged at revision: | 722 |
Proposed branch: | lp:~anso/nova/smoketests_fixes |
Merge into: | lp:~hudson-openstack/nova/trunk |
Prerequisite: | lp:~vishvananda/nova/fix-describe-groups |
Diff against target: |
798 lines (+339/-211) 8 files modified
contrib/nova.sh (+7/-5) nova/__init__.py (+0/-2) smoketests/base.py (+52/-8) smoketests/flags.py (+2/-2) smoketests/netadmin_smoketests.py (+194/-0) smoketests/proxy.sh (+22/-0) smoketests/public_network_smoketests.py (+9/-2) smoketests/sysadmin_smoketests.py (+53/-192) |
To merge this branch: | bzr merge lp:~anso/nova/smoketests_fixes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Devin Carlen (community) | Approve | ||
Jay Pipes (community) | Approve | ||
Review via email: mp+50850@code.launchpad.net |
Commit message
Fixes existing smoketests and splits out sysadmin tests from netadmin tests.
* sets use_ipv6 = False by default
* switches to ami-tty for tests
* generally improves error handling
Description of the change
Fixes existing smoketests and splits out sysadmin tests from netadmin tests.
* sets use_ipv6 = False by default
* switches to ami-tty for tests
* generally improves error handling
There is a lot more that can be done here, but I want to get this out so people actually start running them and adding more.
To run the tests:
source an rc file (make sure that it comes from a nova.zip if you want to test image uploading)
cd smoketests
python admin_smoketests.py
python sysadmin_
python netadmin_
Future cleanup:
* Run all of the available tests with nose
* Prettify the output (a la our tests in nova)
* Some of public_
* Add more tests for other api commands.
* Tests for functionality (can the instance get to the public internet, etc.)
Devin Carlen (devcamcar) wrote : | # |
cool, looks good
OpenStack Infra (hudson-openstack) wrote : | # |
The prerequisite lp:~vishvananda/nova/fix-describe-groups has not yet been merged into lp:nova.
Vish Ishaya (vishvananda) wrote : | # |
reapproving now that prereq branch is in.
Nachi Ueno (nati-ueno) wrote : | # |
Hi Vish
We will work for
* Some of public_
If you have any idea for design test for some network topology ( Single Node environment in which Compute node and Network node stay in same box, Multi-Node in which Compute node and Network node stay in different box or Multiple Network node environment, would you tell me that?
Preview Diff
1 | === modified file 'contrib/nova.sh' | |||
2 | --- contrib/nova.sh 2011-01-21 23:48:10 +0000 | |||
3 | +++ contrib/nova.sh 2011-02-23 02:16:10 +0000 | |||
4 | @@ -66,7 +66,7 @@ | |||
5 | 66 | sudo apt-get install -y user-mode-linux kvm libvirt-bin | 66 | sudo apt-get install -y user-mode-linux kvm libvirt-bin |
6 | 67 | sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server | 67 | sudo apt-get install -y screen euca2ools vlan curl rabbitmq-server |
7 | 68 | sudo apt-get install -y lvm2 iscsitarget open-iscsi | 68 | sudo apt-get install -y lvm2 iscsitarget open-iscsi |
9 | 69 | sudo apt-get install -y socat | 69 | sudo apt-get install -y socat unzip |
10 | 70 | echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget | 70 | echo "ISCSITARGET_ENABLE=true" | sudo tee /etc/default/iscsitarget |
11 | 71 | sudo /etc/init.d/iscsitarget restart | 71 | sudo /etc/init.d/iscsitarget restart |
12 | 72 | sudo modprobe kvm | 72 | sudo modprobe kvm |
13 | @@ -111,8 +111,7 @@ | |||
14 | 111 | --nodaemon | 111 | --nodaemon |
15 | 112 | --dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf | 112 | --dhcpbridge_flagfile=$NOVA_DIR/bin/nova.conf |
16 | 113 | --network_manager=nova.network.manager.$NET_MAN | 113 | --network_manager=nova.network.manager.$NET_MAN |
19 | 114 | --cc_host=$HOST_IP | 114 | --my_ip=$HOST_IP |
18 | 115 | --routing_source_ip=$HOST_IP | ||
20 | 116 | --sql_connection=$SQL_CONN | 115 | --sql_connection=$SQL_CONN |
21 | 117 | --auth_driver=nova.auth.$AUTH | 116 | --auth_driver=nova.auth.$AUTH |
22 | 118 | --libvirt_type=$LIBVIRT_TYPE | 117 | --libvirt_type=$LIBVIRT_TYPE |
23 | @@ -151,7 +150,6 @@ | |||
24 | 151 | mkdir -p $NOVA_DIR/instances | 150 | mkdir -p $NOVA_DIR/instances |
25 | 152 | rm -rf $NOVA_DIR/networks | 151 | rm -rf $NOVA_DIR/networks |
26 | 153 | mkdir -p $NOVA_DIR/networks | 152 | mkdir -p $NOVA_DIR/networks |
27 | 154 | $NOVA_DIR/tools/clean-vlans | ||
28 | 155 | if [ ! -d "$NOVA_DIR/images" ]; then | 153 | if [ ! -d "$NOVA_DIR/images" ]; then |
29 | 156 | ln -s $DIR/images $NOVA_DIR/images | 154 | ln -s $DIR/images $NOVA_DIR/images |
30 | 157 | fi | 155 | fi |
31 | @@ -169,10 +167,14 @@ | |||
32 | 169 | # create a project called 'admin' with project manager of 'admin' | 167 | # create a project called 'admin' with project manager of 'admin' |
33 | 170 | $NOVA_DIR/bin/nova-manage project create admin admin | 168 | $NOVA_DIR/bin/nova-manage project create admin admin |
34 | 171 | # export environment variables for project 'admin' and user 'admin' | 169 | # export environment variables for project 'admin' and user 'admin' |
36 | 172 | $NOVA_DIR/bin/nova-manage project environment admin admin $NOVA_DIR/novarc | 170 | $NOVA_DIR/bin/nova-manage project zipfile admin admin $NOVA_DIR/nova.zip |
37 | 171 | unzip -o $NOVA_DIR/nova.zip -d $NOVA_DIR/ | ||
38 | 173 | # create a small network | 172 | # create a small network |
39 | 174 | $NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 1 32 | 173 | $NOVA_DIR/bin/nova-manage network create 10.0.0.0/8 1 32 |
40 | 175 | 174 | ||
41 | 175 | # create some floating ips | ||
42 | 176 | $NOVA_DIR/bin/nova-manage floating create `hostname` 10.6.0.0/27 | ||
43 | 177 | |||
44 | 176 | # nova api crashes if we start it with a regular screen command, | 178 | # nova api crashes if we start it with a regular screen command, |
45 | 177 | # so send the start command by forcing text into the window. | 179 | # so send the start command by forcing text into the window. |
46 | 178 | screen_it api "$NOVA_DIR/bin/nova-api" | 180 | screen_it api "$NOVA_DIR/bin/nova-api" |
47 | 179 | 181 | ||
48 | === modified file 'nova/__init__.py' | |||
49 | --- nova/__init__.py 2010-07-15 15:52:11 +0000 | |||
50 | +++ nova/__init__.py 2011-02-23 02:16:10 +0000 | |||
51 | @@ -30,5 +30,3 @@ | |||
52 | 30 | .. moduleauthor:: Manish Singh <yosh@gimp.org> | 30 | .. moduleauthor:: Manish Singh <yosh@gimp.org> |
53 | 31 | .. moduleauthor:: Andy Smith <andy@anarkystic.com> | 31 | .. moduleauthor:: Andy Smith <andy@anarkystic.com> |
54 | 32 | """ | 32 | """ |
55 | 33 | |||
56 | 34 | from exception import * | ||
57 | 35 | 33 | ||
58 | === modified file 'smoketests/base.py' | |||
59 | --- smoketests/base.py 2010-12-24 11:38:49 +0000 | |||
60 | +++ smoketests/base.py 2011-02-23 02:16:10 +0000 | |||
61 | @@ -17,19 +17,21 @@ | |||
62 | 17 | # under the License. | 17 | # under the License. |
63 | 18 | 18 | ||
64 | 19 | import boto | 19 | import boto |
65 | 20 | import boto_v6 | ||
66 | 21 | import commands | 20 | import commands |
67 | 22 | import httplib | 21 | import httplib |
68 | 23 | import os | 22 | import os |
69 | 24 | import paramiko | 23 | import paramiko |
70 | 25 | import random | ||
71 | 26 | import sys | 24 | import sys |
72 | 25 | import time | ||
73 | 27 | import unittest | 26 | import unittest |
74 | 28 | from boto.ec2.regioninfo import RegionInfo | 27 | from boto.ec2.regioninfo import RegionInfo |
75 | 29 | 28 | ||
76 | 30 | from smoketests import flags | 29 | from smoketests import flags |
77 | 31 | 30 | ||
78 | 31 | SUITE_NAMES = '[image, instance, volume]' | ||
79 | 32 | FLAGS = flags.FLAGS | 32 | FLAGS = flags.FLAGS |
80 | 33 | flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES) | ||
81 | 34 | boto_v6 = None | ||
82 | 33 | 35 | ||
83 | 34 | 36 | ||
84 | 35 | class SmokeTestCase(unittest.TestCase): | 37 | class SmokeTestCase(unittest.TestCase): |
85 | @@ -39,12 +41,10 @@ | |||
86 | 39 | client = paramiko.SSHClient() | 41 | client = paramiko.SSHClient() |
87 | 40 | client.set_missing_host_key_policy(paramiko.WarningPolicy()) | 42 | client.set_missing_host_key_policy(paramiko.WarningPolicy()) |
88 | 41 | client.connect(ip, username='root', pkey=key) | 43 | client.connect(ip, username='root', pkey=key) |
89 | 42 | stdin, stdout, stderr = client.exec_command('uptime') | ||
90 | 43 | print 'uptime: ', stdout.read() | ||
91 | 44 | return client | 44 | return client |
92 | 45 | 45 | ||
95 | 46 | def can_ping(self, ip): | 46 | def can_ping(self, ip, command="ping"): |
96 | 47 | """ Attempt to ping the specified IP, and give up after 1 second. """ | 47 | """Attempt to ping the specified IP, and give up after 1 second.""" |
97 | 48 | 48 | ||
98 | 49 | # NOTE(devcamcar): ping timeout flag is different in OSX. | 49 | # NOTE(devcamcar): ping timeout flag is different in OSX. |
99 | 50 | if sys.platform == 'darwin': | 50 | if sys.platform == 'darwin': |
100 | @@ -52,10 +52,41 @@ | |||
101 | 52 | else: | 52 | else: |
102 | 53 | timeout_flag = 'w' | 53 | timeout_flag = 'w' |
103 | 54 | 54 | ||
106 | 55 | status, output = commands.getstatusoutput('ping -c1 -%s1 %s' % | 55 | status, output = commands.getstatusoutput('%s -c1 -%s1 %s' % |
107 | 56 | (timeout_flag, ip)) | 56 | (command, timeout_flag, ip)) |
108 | 57 | return status == 0 | 57 | return status == 0 |
109 | 58 | 58 | ||
110 | 59 | def wait_for_running(self, instance, tries=60, wait=1): | ||
111 | 60 | """Wait for instance to be running""" | ||
112 | 61 | for x in xrange(tries): | ||
113 | 62 | instance.update() | ||
114 | 63 | if instance.state.startswith('running'): | ||
115 | 64 | return True | ||
116 | 65 | time.sleep(wait) | ||
117 | 66 | else: | ||
118 | 67 | return False | ||
119 | 68 | |||
120 | 69 | def wait_for_ping(self, ip, command="ping", tries=120): | ||
121 | 70 | """Wait for ip to be pingable""" | ||
122 | 71 | for x in xrange(tries): | ||
123 | 72 | if self.can_ping(ip, command): | ||
124 | 73 | return True | ||
125 | 74 | else: | ||
126 | 75 | return False | ||
127 | 76 | |||
128 | 77 | def wait_for_ssh(self, ip, key_name, tries=30, wait=5): | ||
129 | 78 | """Wait for ip to be sshable""" | ||
130 | 79 | for x in xrange(tries): | ||
131 | 80 | try: | ||
132 | 81 | conn = self.connect_ssh(ip, key_name) | ||
133 | 82 | conn.close() | ||
134 | 83 | except Exception, e: | ||
135 | 84 | time.sleep(wait) | ||
136 | 85 | else: | ||
137 | 86 | return True | ||
138 | 87 | else: | ||
139 | 88 | return False | ||
140 | 89 | |||
141 | 59 | def connection_for_env(self, **kwargs): | 90 | def connection_for_env(self, **kwargs): |
142 | 60 | """ | 91 | """ |
143 | 61 | Returns a boto ec2 connection for the current environment. | 92 | Returns a boto ec2 connection for the current environment. |
144 | @@ -144,8 +175,21 @@ | |||
145 | 144 | return True | 175 | return True |
146 | 145 | 176 | ||
147 | 146 | 177 | ||
148 | 178 | TEST_DATA = {} | ||
149 | 179 | |||
150 | 180 | |||
151 | 181 | class UserSmokeTestCase(SmokeTestCase): | ||
152 | 182 | def setUp(self): | ||
153 | 183 | global TEST_DATA | ||
154 | 184 | self.conn = self.connection_for_env() | ||
155 | 185 | self.data = TEST_DATA | ||
156 | 186 | |||
157 | 187 | |||
158 | 147 | def run_tests(suites): | 188 | def run_tests(suites): |
159 | 148 | argv = FLAGS(sys.argv) | 189 | argv = FLAGS(sys.argv) |
160 | 190 | if FLAGS.use_ipv6: | ||
161 | 191 | global boto_v6 | ||
162 | 192 | boto_v6 = __import__('boto_v6') | ||
163 | 149 | 193 | ||
164 | 150 | if not os.getenv('EC2_ACCESS_KEY'): | 194 | if not os.getenv('EC2_ACCESS_KEY'): |
165 | 151 | print >> sys.stderr, 'Missing EC2 environment variables. Please ' \ | 195 | print >> sys.stderr, 'Missing EC2 environment variables. Please ' \ |
166 | 152 | 196 | ||
167 | === modified file 'smoketests/flags.py' | |||
168 | --- smoketests/flags.py 2010-12-24 11:38:49 +0000 | |||
169 | +++ smoketests/flags.py 2011-02-23 02:16:10 +0000 | |||
170 | @@ -35,5 +35,5 @@ | |||
171 | 35 | # http://code.google.com/p/python-gflags/source/browse/trunk/gflags.py#39 | 35 | # http://code.google.com/p/python-gflags/source/browse/trunk/gflags.py#39 |
172 | 36 | 36 | ||
173 | 37 | DEFINE_string('region', 'nova', 'Region to use') | 37 | DEFINE_string('region', 'nova', 'Region to use') |
176 | 38 | DEFINE_string('test_image', 'ami-tiny', 'Image to use for launch tests') | 38 | DEFINE_string('test_image', 'ami-tty', 'Image to use for launch tests') |
177 | 39 | DEFINE_string('use_ipv6', True, 'use the ipv6 or not') | 39 | DEFINE_bool('use_ipv6', False, 'use the ipv6 or not') |
178 | 40 | 40 | ||
179 | === added file 'smoketests/netadmin_smoketests.py' | |||
180 | --- smoketests/netadmin_smoketests.py 1970-01-01 00:00:00 +0000 | |||
181 | +++ smoketests/netadmin_smoketests.py 2011-02-23 02:16:10 +0000 | |||
182 | @@ -0,0 +1,194 @@ | |||
183 | 1 | # vim: tabstop=4 shiftwidth=4 softtabstop=4 | ||
184 | 2 | |||
185 | 3 | # Copyright 2010 United States Government as represented by the | ||
186 | 4 | # Administrator of the National Aeronautics and Space Administration. | ||
187 | 5 | # All Rights Reserved. | ||
188 | 6 | # | ||
189 | 7 | # Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
190 | 8 | # not use this file except in compliance with the License. You may obtain | ||
191 | 9 | # a copy of the License at | ||
192 | 10 | # | ||
193 | 11 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
194 | 12 | # | ||
195 | 13 | # Unless required by applicable law or agreed to in writing, software | ||
196 | 14 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
197 | 15 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
198 | 16 | # License for the specific language governing permissions and limitations | ||
199 | 17 | # under the License. | ||
200 | 18 | |||
201 | 19 | import commands | ||
202 | 20 | import os | ||
203 | 21 | import random | ||
204 | 22 | import sys | ||
205 | 23 | import time | ||
206 | 24 | import unittest | ||
207 | 25 | |||
208 | 26 | # If ../nova/__init__.py exists, add ../ to Python search path, so that | ||
209 | 27 | # it will override what happens to be installed in /usr/(local/)lib/python... | ||
210 | 28 | possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), | ||
211 | 29 | os.pardir, | ||
212 | 30 | os.pardir)) | ||
213 | 31 | if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): | ||
214 | 32 | sys.path.insert(0, possible_topdir) | ||
215 | 33 | |||
216 | 34 | from smoketests import flags | ||
217 | 35 | from smoketests import base | ||
218 | 36 | |||
219 | 37 | |||
220 | 38 | FLAGS = flags.FLAGS | ||
221 | 39 | |||
222 | 40 | TEST_PREFIX = 'test%s' % int(random.random() * 1000000) | ||
223 | 41 | TEST_BUCKET = '%s_bucket' % TEST_PREFIX | ||
224 | 42 | TEST_KEY = '%s_key' % TEST_PREFIX | ||
225 | 43 | TEST_GROUP = '%s_group' % TEST_PREFIX | ||
226 | 44 | |||
227 | 45 | |||
228 | 46 | class AddressTests(base.UserSmokeTestCase): | ||
229 | 47 | def test_000_setUp(self): | ||
230 | 48 | self.create_key_pair(self.conn, TEST_KEY) | ||
231 | 49 | reservation = self.conn.run_instances(FLAGS.test_image, | ||
232 | 50 | instance_type='m1.tiny', | ||
233 | 51 | key_name=TEST_KEY) | ||
234 | 52 | self.data['instance'] = reservation.instances[0] | ||
235 | 53 | if not self.wait_for_running(self.data['instance']): | ||
236 | 54 | self.fail('instance failed to start') | ||
237 | 55 | self.data['instance'].update() | ||
238 | 56 | if not self.wait_for_ping(self.data['instance'].private_dns_name): | ||
239 | 57 | self.fail('could not ping instance') | ||
240 | 58 | if not self.wait_for_ssh(self.data['instance'].private_dns_name, | ||
241 | 59 | TEST_KEY): | ||
242 | 60 | self.fail('could not ssh to instance') | ||
243 | 61 | |||
244 | 62 | def test_001_can_allocate_floating_ip(self): | ||
245 | 63 | result = self.conn.allocate_address() | ||
246 | 64 | self.assertTrue(hasattr(result, 'public_ip')) | ||
247 | 65 | self.data['public_ip'] = result.public_ip | ||
248 | 66 | |||
249 | 67 | def test_002_can_associate_ip_with_instance(self): | ||
250 | 68 | result = self.conn.associate_address(self.data['instance'].id, | ||
251 | 69 | self.data['public_ip']) | ||
252 | 70 | self.assertTrue(result) | ||
253 | 71 | |||
254 | 72 | def test_003_can_ssh_with_public_ip(self): | ||
255 | 73 | ssh_authorized = False | ||
256 | 74 | groups = self.conn.get_all_security_groups(['default']) | ||
257 | 75 | for rule in groups[0].rules: | ||
258 | 76 | if (rule.ip_protocol == 'tcp' and | ||
259 | 77 | rule.from_port <= 22 and rule.to_port >= 22): | ||
260 | 78 | ssh_authorized = True | ||
261 | 79 | if not ssh_authorized: | ||
262 | 80 | self.conn.authorize_security_group('default', | ||
263 | 81 | ip_protocol='tcp', | ||
264 | 82 | from_port=22, | ||
265 | 83 | to_port=22) | ||
266 | 84 | try: | ||
267 | 85 | if not self.wait_for_ssh(self.data['public_ip'], TEST_KEY): | ||
268 | 86 | self.fail('could not ssh to public ip') | ||
269 | 87 | finally: | ||
270 | 88 | if not ssh_authorized: | ||
271 | 89 | self.conn.revoke_security_group('default', | ||
272 | 90 | ip_protocol='tcp', | ||
273 | 91 | from_port=22, | ||
274 | 92 | to_port=22) | ||
275 | 93 | |||
276 | 94 | def test_004_can_disassociate_ip_from_instance(self): | ||
277 | 95 | result = self.conn.disassociate_address(self.data['public_ip']) | ||
278 | 96 | self.assertTrue(result) | ||
279 | 97 | |||
280 | 98 | def test_005_can_deallocate_floating_ip(self): | ||
281 | 99 | result = self.conn.release_address(self.data['public_ip']) | ||
282 | 100 | self.assertTrue(result) | ||
283 | 101 | |||
284 | 102 | def test_999_tearDown(self): | ||
285 | 103 | self.delete_key_pair(self.conn, TEST_KEY) | ||
286 | 104 | self.conn.terminate_instances([self.data['instance'].id]) | ||
287 | 105 | |||
288 | 106 | |||
289 | 107 | class SecurityGroupTests(base.UserSmokeTestCase): | ||
290 | 108 | |||
291 | 109 | def __public_instance_is_accessible(self): | ||
292 | 110 | id_url = "latest/meta-data/instance-id" | ||
293 | 111 | options = "-s --max-time 1" | ||
294 | 112 | command = "curl %s %s/%s" % (options, self.data['public_ip'], id_url) | ||
295 | 113 | instance_id = commands.getoutput(command).strip() | ||
296 | 114 | if not instance_id: | ||
297 | 115 | return False | ||
298 | 116 | if instance_id != self.data['instance'].id: | ||
299 | 117 | raise Exception("Wrong instance id") | ||
300 | 118 | return True | ||
301 | 119 | |||
302 | 120 | def test_001_can_create_security_group(self): | ||
303 | 121 | self.conn.create_security_group(TEST_GROUP, description='test') | ||
304 | 122 | |||
305 | 123 | groups = self.conn.get_all_security_groups() | ||
306 | 124 | self.assertTrue(TEST_GROUP in [group.name for group in groups]) | ||
307 | 125 | |||
308 | 126 | def test_002_can_launch_instance_in_security_group(self): | ||
309 | 127 | with open("proxy.sh") as f: | ||
310 | 128 | user_data = f.read() | ||
311 | 129 | self.create_key_pair(self.conn, TEST_KEY) | ||
312 | 130 | reservation = self.conn.run_instances(FLAGS.test_image, | ||
313 | 131 | key_name=TEST_KEY, | ||
314 | 132 | security_groups=[TEST_GROUP], | ||
315 | 133 | user_data=user_data, | ||
316 | 134 | instance_type='m1.tiny') | ||
317 | 135 | |||
318 | 136 | self.data['instance'] = reservation.instances[0] | ||
319 | 137 | if not self.wait_for_running(self.data['instance']): | ||
320 | 138 | self.fail('instance failed to start') | ||
321 | 139 | self.data['instance'].update() | ||
322 | 140 | if not self.wait_for_ping(self.data['instance'].private_dns_name): | ||
323 | 141 | self.fail('could not ping instance') | ||
324 | 142 | if not self.wait_for_ssh(self.data['instance'].private_dns_name, | ||
325 | 143 | TEST_KEY): | ||
326 | 144 | self.fail('could not ssh to instance') | ||
327 | 145 | |||
328 | 146 | def test_003_can_authorize_security_group_ingress(self): | ||
329 | 147 | self.assertTrue(self.conn.authorize_security_group(TEST_GROUP, | ||
330 | 148 | ip_protocol='tcp', | ||
331 | 149 | from_port=80, | ||
332 | 150 | to_port=80)) | ||
333 | 151 | |||
334 | 152 | def test_004_can_access_metadata_over_public_ip(self): | ||
335 | 153 | result = self.conn.allocate_address() | ||
336 | 154 | self.assertTrue(hasattr(result, 'public_ip')) | ||
337 | 155 | self.data['public_ip'] = result.public_ip | ||
338 | 156 | |||
339 | 157 | result = self.conn.associate_address(self.data['instance'].id, | ||
340 | 158 | self.data['public_ip']) | ||
341 | 159 | start_time = time.time() | ||
342 | 160 | try: | ||
343 | 161 | while not self.__public_instance_is_accessible(): | ||
344 | 162 | # 1 minute to launch | ||
345 | 163 | if time.time() - start_time > 60: | ||
346 | 164 | raise Exception("Timeout") | ||
347 | 165 | time.sleep(1) | ||
348 | 166 | finally: | ||
349 | 167 | result = self.conn.disassociate_address(self.data['public_ip']) | ||
350 | 168 | |||
351 | 169 | def test_005_can_revoke_security_group_ingress(self): | ||
352 | 170 | self.assertTrue(self.conn.revoke_security_group(TEST_GROUP, | ||
353 | 171 | ip_protocol='tcp', | ||
354 | 172 | from_port=80, | ||
355 | 173 | to_port=80)) | ||
356 | 174 | start_time = time.time() | ||
357 | 175 | while self.__public_instance_is_accessible(): | ||
358 | 176 | # 1 minute to teardown | ||
359 | 177 | if time.time() - start_time > 60: | ||
360 | 178 | raise Exception("Timeout") | ||
361 | 179 | time.sleep(1) | ||
362 | 180 | |||
363 | 181 | def test_999_tearDown(self): | ||
364 | 182 | self.conn.delete_key_pair(TEST_KEY) | ||
365 | 183 | self.conn.delete_security_group(TEST_GROUP) | ||
366 | 184 | groups = self.conn.get_all_security_groups() | ||
367 | 185 | self.assertFalse(TEST_GROUP in [group.name for group in groups]) | ||
368 | 186 | self.conn.terminate_instances([self.data['instance'].id]) | ||
369 | 187 | self.assertTrue(self.conn.release_address(self.data['public_ip'])) | ||
370 | 188 | |||
371 | 189 | |||
372 | 190 | if __name__ == "__main__": | ||
373 | 191 | suites = {'address': unittest.makeSuite(AddressTests), | ||
374 | 192 | 'security_group': unittest.makeSuite(SecurityGroupTests) | ||
375 | 193 | } | ||
376 | 194 | sys.exit(base.run_tests(suites)) | ||
377 | 0 | 195 | ||
378 | === added file 'smoketests/proxy.sh' | |||
379 | --- smoketests/proxy.sh 1970-01-01 00:00:00 +0000 | |||
380 | +++ smoketests/proxy.sh 2011-02-23 02:16:10 +0000 | |||
381 | @@ -0,0 +1,22 @@ | |||
382 | 1 | #!/usr/bin/env bash | ||
383 | 2 | |||
384 | 3 | # This is a simple shell script that uses netcat to set up a proxy to the | ||
385 | 4 | # metadata server on port 80 and to a google ip on port 8080. This is meant | ||
386 | 5 | # to be passed in by a script to an instance via user data, so that | ||
387 | 6 | # automatic testing of network connectivity can be performed. | ||
388 | 7 | |||
389 | 8 | # Example usage: | ||
390 | 9 | # euca-run-instances -t m1.tiny -f proxy.sh ami-tty | ||
391 | 10 | |||
392 | 11 | mkfifo backpipe1 | ||
393 | 12 | mkfifo backpipe2 | ||
394 | 13 | |||
395 | 14 | # NOTE(vish): proxy metadata on port 80 | ||
396 | 15 | while true; do | ||
397 | 16 | nc -l -p 80 0<backpipe1 | nc 169.254.169.254 80 1>backpipe1 | ||
398 | 17 | done & | ||
399 | 18 | |||
400 | 19 | # NOTE(vish): proxy google on port 8080 | ||
401 | 20 | while true; do | ||
402 | 21 | nc -l -p 8080 0<backpipe2 | nc 74.125.19.99 80 1>backpipe2 | ||
403 | 22 | done & | ||
404 | 0 | 23 | ||
405 | === modified file 'smoketests/public_network_smoketests.py' | |||
406 | --- smoketests/public_network_smoketests.py 2010-12-24 11:38:49 +0000 | |||
407 | +++ smoketests/public_network_smoketests.py 2011-02-23 02:16:10 +0000 | |||
408 | @@ -24,9 +24,16 @@ | |||
409 | 24 | import time | 24 | import time |
410 | 25 | import unittest | 25 | import unittest |
411 | 26 | 26 | ||
412 | 27 | # If ../nova/__init__.py exists, add ../ to Python search path, so that | ||
413 | 28 | # it will override what happens to be installed in /usr/(local/)lib/python... | ||
414 | 29 | possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), | ||
415 | 30 | os.pardir, | ||
416 | 31 | os.pardir)) | ||
417 | 32 | if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): | ||
418 | 33 | sys.path.insert(0, possible_topdir) | ||
419 | 34 | |||
420 | 27 | from smoketests import flags | 35 | from smoketests import flags |
421 | 28 | from smoketests import base | 36 | from smoketests import base |
422 | 29 | from smoketests import user_smoketests | ||
423 | 30 | 37 | ||
424 | 31 | #Note that this test should run from | 38 | #Note that this test should run from |
425 | 32 | #public network (outside of private network segments) | 39 | #public network (outside of private network segments) |
426 | @@ -42,7 +49,7 @@ | |||
427 | 42 | TEST_DATA = {} | 49 | TEST_DATA = {} |
428 | 43 | 50 | ||
429 | 44 | 51 | ||
431 | 45 | class InstanceTestsFromPublic(user_smoketests.UserSmokeTestCase): | 52 | class InstanceTestsFromPublic(base.UserSmokeTestCase): |
432 | 46 | def test_001_can_create_keypair(self): | 53 | def test_001_can_create_keypair(self): |
433 | 47 | key = self.create_key_pair(self.conn, TEST_KEY) | 54 | key = self.create_key_pair(self.conn, TEST_KEY) |
434 | 48 | self.assertEqual(key.name, TEST_KEY) | 55 | self.assertEqual(key.name, TEST_KEY) |
435 | 49 | 56 | ||
436 | === renamed file 'smoketests/user_smoketests.py' => 'smoketests/sysadmin_smoketests.py' | |||
437 | --- smoketests/user_smoketests.py 2011-01-12 08:47:54 +0000 | |||
438 | +++ smoketests/sysadmin_smoketests.py 2011-02-23 02:16:10 +0000 | |||
439 | @@ -19,7 +19,6 @@ | |||
440 | 19 | import commands | 19 | import commands |
441 | 20 | import os | 20 | import os |
442 | 21 | import random | 21 | import random |
443 | 22 | import socket | ||
444 | 23 | import sys | 22 | import sys |
445 | 24 | import time | 23 | import time |
446 | 25 | import unittest | 24 | import unittest |
447 | @@ -36,10 +35,8 @@ | |||
448 | 36 | from smoketests import base | 35 | from smoketests import base |
449 | 37 | 36 | ||
450 | 38 | 37 | ||
451 | 39 | SUITE_NAMES = '[image, instance, volume]' | ||
452 | 40 | 38 | ||
453 | 41 | FLAGS = flags.FLAGS | 39 | FLAGS = flags.FLAGS |
454 | 42 | flags.DEFINE_string('suite', None, 'Specific test suite to run ' + SUITE_NAMES) | ||
455 | 43 | flags.DEFINE_string('bundle_kernel', 'openwrt-x86-vmlinuz', | 40 | flags.DEFINE_string('bundle_kernel', 'openwrt-x86-vmlinuz', |
456 | 44 | 'Local kernel file to use for bundling tests') | 41 | 'Local kernel file to use for bundling tests') |
457 | 45 | flags.DEFINE_string('bundle_image', 'openwrt-x86-ext2.image', | 42 | flags.DEFINE_string('bundle_image', 'openwrt-x86-ext2.image', |
458 | @@ -49,17 +46,7 @@ | |||
459 | 49 | TEST_BUCKET = '%s_bucket' % TEST_PREFIX | 46 | TEST_BUCKET = '%s_bucket' % TEST_PREFIX |
460 | 50 | TEST_KEY = '%s_key' % TEST_PREFIX | 47 | TEST_KEY = '%s_key' % TEST_PREFIX |
461 | 51 | TEST_GROUP = '%s_group' % TEST_PREFIX | 48 | TEST_GROUP = '%s_group' % TEST_PREFIX |
473 | 52 | TEST_DATA = {} | 49 | class ImageTests(base.UserSmokeTestCase): |
463 | 53 | |||
464 | 54 | |||
465 | 55 | class UserSmokeTestCase(base.SmokeTestCase): | ||
466 | 56 | def setUp(self): | ||
467 | 57 | global TEST_DATA | ||
468 | 58 | self.conn = self.connection_for_env() | ||
469 | 59 | self.data = TEST_DATA | ||
470 | 60 | |||
471 | 61 | |||
472 | 62 | class ImageTests(UserSmokeTestCase): | ||
474 | 63 | def test_001_can_bundle_image(self): | 50 | def test_001_can_bundle_image(self): |
475 | 64 | self.assertTrue(self.bundle_image(FLAGS.bundle_image)) | 51 | self.assertTrue(self.bundle_image(FLAGS.bundle_image)) |
476 | 65 | 52 | ||
477 | @@ -91,7 +78,6 @@ | |||
478 | 91 | break | 78 | break |
479 | 92 | time.sleep(1) | 79 | time.sleep(1) |
480 | 93 | else: | 80 | else: |
481 | 94 | print image.state | ||
482 | 95 | self.assert_(False) # wasn't available within 10 seconds | 81 | self.assert_(False) # wasn't available within 10 seconds |
483 | 96 | self.assert_(image.type == 'machine') | 82 | self.assert_(image.type == 'machine') |
484 | 97 | 83 | ||
485 | @@ -133,7 +119,7 @@ | |||
486 | 133 | self.assertTrue(self.delete_bundle_bucket(TEST_BUCKET)) | 119 | self.assertTrue(self.delete_bundle_bucket(TEST_BUCKET)) |
487 | 134 | 120 | ||
488 | 135 | 121 | ||
490 | 136 | class InstanceTests(UserSmokeTestCase): | 122 | class InstanceTests(base.UserSmokeTestCase): |
491 | 137 | def test_001_can_create_keypair(self): | 123 | def test_001_can_create_keypair(self): |
492 | 138 | key = self.create_key_pair(self.conn, TEST_KEY) | 124 | key = self.create_key_pair(self.conn, TEST_KEY) |
493 | 139 | self.assertEqual(key.name, TEST_KEY) | 125 | self.assertEqual(key.name, TEST_KEY) |
494 | @@ -143,109 +129,44 @@ | |||
495 | 143 | key_name=TEST_KEY, | 129 | key_name=TEST_KEY, |
496 | 144 | instance_type='m1.tiny') | 130 | instance_type='m1.tiny') |
497 | 145 | self.assertEqual(len(reservation.instances), 1) | 131 | self.assertEqual(len(reservation.instances), 1) |
499 | 146 | self.data['instance_id'] = reservation.instances[0].id | 132 | self.data['instance'] = reservation.instances[0] |
500 | 147 | 133 | ||
501 | 148 | def test_003_instance_runs_within_60_seconds(self): | 134 | def test_003_instance_runs_within_60_seconds(self): |
504 | 149 | reservations = self.conn.get_all_instances([self.data['instance_id']]) | 135 | instance = self.data['instance'] |
503 | 150 | instance = reservations[0].instances[0] | ||
505 | 151 | # allow 60 seconds to exit pending with IP | 136 | # allow 60 seconds to exit pending with IP |
512 | 152 | for x in xrange(60): | 137 | if not self.wait_for_running(self.data['instance']): |
507 | 153 | instance.update() | ||
508 | 154 | if instance.state == u'running': | ||
509 | 155 | break | ||
510 | 156 | time.sleep(1) | ||
511 | 157 | else: | ||
513 | 158 | self.fail('instance failed to start') | 138 | self.fail('instance failed to start') |
515 | 159 | ip = reservations[0].instances[0].private_dns_name | 139 | self.data['instance'].update() |
516 | 140 | ip = self.data['instance'].private_dns_name | ||
517 | 160 | self.failIf(ip == '0.0.0.0') | 141 | self.failIf(ip == '0.0.0.0') |
518 | 161 | self.data['private_ip'] = ip | ||
519 | 162 | if FLAGS.use_ipv6: | 142 | if FLAGS.use_ipv6: |
521 | 163 | ipv6 = reservations[0].instances[0].dns_name_v6 | 143 | ipv6 = self.data['instance'].dns_name_v6 |
522 | 164 | self.failIf(ipv6 is None) | 144 | self.failIf(ipv6 is None) |
523 | 165 | self.data['ip_v6'] = ipv6 | ||
524 | 166 | 145 | ||
525 | 167 | def test_004_can_ping_private_ip(self): | 146 | def test_004_can_ping_private_ip(self): |
533 | 168 | for x in xrange(120): | 147 | if not self.wait_for_ping(self.data['instance'].private_dns_name): |
527 | 169 | # ping waits for 1 second | ||
528 | 170 | status, output = commands.getstatusoutput( | ||
529 | 171 | 'ping -c1 %s' % self.data['private_ip']) | ||
530 | 172 | if status == 0: | ||
531 | 173 | break | ||
532 | 174 | else: | ||
534 | 175 | self.fail('could not ping instance') | 148 | self.fail('could not ping instance') |
535 | 176 | 149 | ||
536 | 177 | if FLAGS.use_ipv6: | 150 | if FLAGS.use_ipv6: |
545 | 178 | for x in xrange(120): | 151 | if not self.wait_for_ping(self.data['instance'].ip_v6, "ping6"): |
546 | 179 | # ping waits for 1 second | 152 | self.fail('could not ping instance v6') |
539 | 180 | status, output = commands.getstatusoutput( | ||
540 | 181 | 'ping6 -c1 %s' % self.data['ip_v6']) | ||
541 | 182 | if status == 0: | ||
542 | 183 | break | ||
543 | 184 | else: | ||
544 | 185 | self.fail('could not ping instance') | ||
547 | 186 | 153 | ||
548 | 187 | def test_005_can_ssh_to_private_ip(self): | 154 | def test_005_can_ssh_to_private_ip(self): |
558 | 188 | for x in xrange(30): | 155 | if not self.wait_for_ssh(self.data['instance'].private_dns_name, |
559 | 189 | try: | 156 | TEST_KEY): |
551 | 190 | conn = self.connect_ssh(self.data['private_ip'], TEST_KEY) | ||
552 | 191 | conn.close() | ||
553 | 192 | except Exception: | ||
554 | 193 | time.sleep(1) | ||
555 | 194 | else: | ||
556 | 195 | break | ||
557 | 196 | else: | ||
560 | 197 | self.fail('could not ssh to instance') | 157 | self.fail('could not ssh to instance') |
561 | 198 | 158 | ||
562 | 199 | if FLAGS.use_ipv6: | 159 | if FLAGS.use_ipv6: |
573 | 200 | for x in xrange(30): | 160 | if not self.wait_for_ssh(self.data['instance'].ip_v6, |
574 | 201 | try: | 161 | TEST_KEY): |
565 | 202 | conn = self.connect_ssh( | ||
566 | 203 | self.data['ip_v6'], TEST_KEY) | ||
567 | 204 | conn.close() | ||
568 | 205 | except Exception: | ||
569 | 206 | time.sleep(1) | ||
570 | 207 | else: | ||
571 | 208 | break | ||
572 | 209 | else: | ||
575 | 210 | self.fail('could not ssh to instance v6') | 162 | self.fail('could not ssh to instance v6') |
576 | 211 | 163 | ||
577 | 212 | def test_006_can_allocate_elastic_ip(self): | ||
578 | 213 | result = self.conn.allocate_address() | ||
579 | 214 | self.assertTrue(hasattr(result, 'public_ip')) | ||
580 | 215 | self.data['public_ip'] = result.public_ip | ||
581 | 216 | |||
582 | 217 | def test_007_can_associate_ip_with_instance(self): | ||
583 | 218 | result = self.conn.associate_address(self.data['instance_id'], | ||
584 | 219 | self.data['public_ip']) | ||
585 | 220 | self.assertTrue(result) | ||
586 | 221 | |||
587 | 222 | def test_008_can_ssh_with_public_ip(self): | ||
588 | 223 | for x in xrange(30): | ||
589 | 224 | try: | ||
590 | 225 | conn = self.connect_ssh(self.data['public_ip'], TEST_KEY) | ||
591 | 226 | conn.close() | ||
592 | 227 | except socket.error: | ||
593 | 228 | time.sleep(1) | ||
594 | 229 | else: | ||
595 | 230 | break | ||
596 | 231 | else: | ||
597 | 232 | self.fail('could not ssh to instance') | ||
598 | 233 | |||
599 | 234 | def test_009_can_disassociate_ip_from_instance(self): | ||
600 | 235 | result = self.conn.disassociate_address(self.data['public_ip']) | ||
601 | 236 | self.assertTrue(result) | ||
602 | 237 | |||
603 | 238 | def test_010_can_deallocate_elastic_ip(self): | ||
604 | 239 | result = self.conn.release_address(self.data['public_ip']) | ||
605 | 240 | self.assertTrue(result) | ||
606 | 241 | |||
607 | 242 | def test_999_tearDown(self): | 164 | def test_999_tearDown(self): |
608 | 243 | self.delete_key_pair(self.conn, TEST_KEY) | 165 | self.delete_key_pair(self.conn, TEST_KEY) |
614 | 244 | if self.data.has_key('instance_id'): | 166 | self.conn.terminate_instances([self.data['instance'].id]) |
615 | 245 | self.conn.terminate_instances([self.data['instance_id']]) | 167 | |
616 | 246 | 168 | ||
617 | 247 | 169 | class VolumeTests(base.UserSmokeTestCase): | |
613 | 248 | class VolumeTests(UserSmokeTestCase): | ||
618 | 249 | def setUp(self): | 170 | def setUp(self): |
619 | 250 | super(VolumeTests, self).setUp() | 171 | super(VolumeTests, self).setUp() |
620 | 251 | self.device = '/dev/vdb' | 172 | self.device = '/dev/vdb' |
621 | @@ -255,55 +176,65 @@ | |||
622 | 255 | reservation = self.conn.run_instances(FLAGS.test_image, | 176 | reservation = self.conn.run_instances(FLAGS.test_image, |
623 | 256 | instance_type='m1.tiny', | 177 | instance_type='m1.tiny', |
624 | 257 | key_name=TEST_KEY) | 178 | key_name=TEST_KEY) |
632 | 258 | instance = reservation.instances[0] | 179 | self.data['instance'] = reservation.instances[0] |
633 | 259 | self.data['instance'] = instance | 180 | if not self.wait_for_running(self.data['instance']): |
634 | 260 | for x in xrange(120): | 181 | self.fail('instance failed to start') |
635 | 261 | if self.can_ping(instance.private_dns_name): | 182 | self.data['instance'].update() |
636 | 262 | break | 183 | if not self.wait_for_ping(self.data['instance'].private_dns_name): |
637 | 263 | else: | 184 | self.fail('could not ping instance') |
638 | 264 | self.fail('unable to start instance') | 185 | if not self.wait_for_ssh(self.data['instance'].private_dns_name, |
639 | 186 | TEST_KEY): | ||
640 | 187 | self.fail('could not ssh to instance') | ||
641 | 265 | 188 | ||
642 | 266 | def test_001_can_create_volume(self): | 189 | def test_001_can_create_volume(self): |
643 | 267 | volume = self.conn.create_volume(1, 'nova') | 190 | volume = self.conn.create_volume(1, 'nova') |
644 | 268 | self.assertEqual(volume.size, 1) | 191 | self.assertEqual(volume.size, 1) |
645 | 269 | self.data['volume'] = volume | 192 | self.data['volume'] = volume |
646 | 270 | # Give network time to find volume. | 193 | # Give network time to find volume. |
648 | 271 | time.sleep(5) | 194 | time.sleep(10) |
649 | 272 | 195 | ||
650 | 273 | def test_002_can_attach_volume(self): | 196 | def test_002_can_attach_volume(self): |
651 | 274 | volume = self.data['volume'] | 197 | volume = self.data['volume'] |
652 | 275 | 198 | ||
653 | 276 | for x in xrange(10): | 199 | for x in xrange(10): |
655 | 277 | if volume.status == u'available': | 200 | volume.update() |
656 | 201 | if volume.status.startswith('available'): | ||
657 | 278 | break | 202 | break |
660 | 279 | time.sleep(5) | 203 | time.sleep(1) |
659 | 280 | volume.update() | ||
661 | 281 | else: | 204 | else: |
662 | 282 | self.fail('cannot attach volume with state %s' % volume.status) | 205 | self.fail('cannot attach volume with state %s' % volume.status) |
663 | 283 | 206 | ||
664 | 284 | volume.attach(self.data['instance'].id, self.device) | 207 | volume.attach(self.data['instance'].id, self.device) |
665 | 285 | 208 | ||
667 | 286 | # Volumes seems to report "available" too soon. | 209 | # wait |
668 | 287 | for x in xrange(10): | 210 | for x in xrange(10): |
670 | 288 | if volume.status == u'in-use': | 211 | volume.update() |
671 | 212 | if volume.status.startswith('in-use'): | ||
672 | 289 | break | 213 | break |
675 | 290 | time.sleep(5) | 214 | time.sleep(1) |
676 | 291 | volume.update() | 215 | else: |
677 | 216 | self.fail('volume never got to in use') | ||
678 | 292 | 217 | ||
680 | 293 | self.assertEqual(volume.status, u'in-use') | 218 | self.assertTrue(volume.status.startswith('in-use')) |
681 | 294 | 219 | ||
682 | 295 | # Give instance time to recognize volume. | 220 | # Give instance time to recognize volume. |
684 | 296 | time.sleep(5) | 221 | time.sleep(10) |
685 | 297 | 222 | ||
686 | 298 | def test_003_can_mount_volume(self): | 223 | def test_003_can_mount_volume(self): |
687 | 299 | ip = self.data['instance'].private_dns_name | 224 | ip = self.data['instance'].private_dns_name |
688 | 300 | conn = self.connect_ssh(ip, TEST_KEY) | 225 | conn = self.connect_ssh(ip, TEST_KEY) |
695 | 301 | commands = [] | 226 | # NOTE(vish): this will create an dev for images that don't have |
696 | 302 | commands.append('mkdir -p /mnt/vol') | 227 | # udev rules |
697 | 303 | commands.append('mkfs.ext2 %s' % self.device) | 228 | stdin, stdout, stderr = conn.exec_command( |
698 | 304 | commands.append('mount %s /mnt/vol' % self.device) | 229 | 'grep %s /proc/partitions | ' |
699 | 305 | commands.append('echo success') | 230 | '`awk \'{print "mknod /dev/"\\$4" b "\\$1" "\\$2}\'`' |
700 | 306 | stdin, stdout, stderr = conn.exec_command(' && '.join(commands)) | 231 | % self.device.rpartition('/')[2]) |
701 | 232 | exec_list = [] | ||
702 | 233 | exec_list.append('mkdir -p /mnt/vol') | ||
703 | 234 | exec_list.append('/sbin/mke2fs %s' % self.device) | ||
704 | 235 | exec_list.append('mount %s /mnt/vol' % self.device) | ||
705 | 236 | exec_list.append('echo success') | ||
706 | 237 | stdin, stdout, stderr = conn.exec_command(' && '.join(exec_list)) | ||
707 | 307 | out = stdout.read() | 238 | out = stdout.read() |
708 | 308 | conn.close() | 239 | conn.close() |
709 | 309 | if not out.strip().endswith('success'): | 240 | if not out.strip().endswith('success'): |
710 | @@ -327,7 +258,7 @@ | |||
711 | 327 | "df -h | grep %s | awk {'print $2'}" % self.device) | 258 | "df -h | grep %s | awk {'print $2'}" % self.device) |
712 | 328 | out = stdout.read() | 259 | out = stdout.read() |
713 | 329 | conn.close() | 260 | conn.close() |
715 | 330 | if not out.strip() == '1008M': | 261 | if not out.strip() == '1007.9M': |
716 | 331 | self.fail('Volume is not the right size: %s %s' % | 262 | self.fail('Volume is not the right size: %s %s' % |
717 | 332 | (out, stderr.read())) | 263 | (out, stderr.read())) |
718 | 333 | 264 | ||
719 | @@ -354,79 +285,9 @@ | |||
720 | 354 | self.conn.delete_key_pair(TEST_KEY) | 285 | self.conn.delete_key_pair(TEST_KEY) |
721 | 355 | 286 | ||
722 | 356 | 287 | ||
723 | 357 | class SecurityGroupTests(UserSmokeTestCase): | ||
724 | 358 | |||
725 | 359 | def __public_instance_is_accessible(self): | ||
726 | 360 | id_url = "latest/meta-data/instance-id" | ||
727 | 361 | options = "-s --max-time 1" | ||
728 | 362 | command = "curl %s %s/%s" % (options, self.data['public_ip'], id_url) | ||
729 | 363 | instance_id = commands.getoutput(command).strip() | ||
730 | 364 | if not instance_id: | ||
731 | 365 | return False | ||
732 | 366 | if instance_id != self.data['instance_id']: | ||
733 | 367 | raise Exception("Wrong instance id") | ||
734 | 368 | return True | ||
735 | 369 | |||
736 | 370 | def test_001_can_create_security_group(self): | ||
737 | 371 | self.conn.create_security_group(TEST_GROUP, description='test') | ||
738 | 372 | |||
739 | 373 | groups = self.conn.get_all_security_groups() | ||
740 | 374 | self.assertTrue(TEST_GROUP in [group.name for group in groups]) | ||
741 | 375 | |||
742 | 376 | def test_002_can_launch_instance_in_security_group(self): | ||
743 | 377 | self.create_key_pair(self.conn, TEST_KEY) | ||
744 | 378 | reservation = self.conn.run_instances(FLAGS.test_image, | ||
745 | 379 | key_name=TEST_KEY, | ||
746 | 380 | security_groups=[TEST_GROUP], | ||
747 | 381 | instance_type='m1.tiny') | ||
748 | 382 | |||
749 | 383 | self.data['instance_id'] = reservation.instances[0].id | ||
750 | 384 | |||
751 | 385 | def test_003_can_authorize_security_group_ingress(self): | ||
752 | 386 | self.assertTrue(self.conn.authorize_security_group(TEST_GROUP, | ||
753 | 387 | ip_protocol='tcp', | ||
754 | 388 | from_port=80, | ||
755 | 389 | to_port=80)) | ||
756 | 390 | |||
757 | 391 | def test_004_can_access_instance_over_public_ip(self): | ||
758 | 392 | result = self.conn.allocate_address() | ||
759 | 393 | self.assertTrue(hasattr(result, 'public_ip')) | ||
760 | 394 | self.data['public_ip'] = result.public_ip | ||
761 | 395 | |||
762 | 396 | result = self.conn.associate_address(self.data['instance_id'], | ||
763 | 397 | self.data['public_ip']) | ||
764 | 398 | start_time = time.time() | ||
765 | 399 | while not self.__public_instance_is_accessible(): | ||
766 | 400 | # 1 minute to launch | ||
767 | 401 | if time.time() - start_time > 60: | ||
768 | 402 | raise Exception("Timeout") | ||
769 | 403 | time.sleep(1) | ||
770 | 404 | |||
771 | 405 | def test_005_can_revoke_security_group_ingress(self): | ||
772 | 406 | self.assertTrue(self.conn.revoke_security_group(TEST_GROUP, | ||
773 | 407 | ip_protocol='tcp', | ||
774 | 408 | from_port=80, | ||
775 | 409 | to_port=80)) | ||
776 | 410 | start_time = time.time() | ||
777 | 411 | while self.__public_instance_is_accessible(): | ||
778 | 412 | # 1 minute to teardown | ||
779 | 413 | if time.time() - start_time > 60: | ||
780 | 414 | raise Exception("Timeout") | ||
781 | 415 | time.sleep(1) | ||
782 | 416 | |||
783 | 417 | def test_999_tearDown(self): | ||
784 | 418 | self.conn.delete_key_pair(TEST_KEY) | ||
785 | 419 | self.conn.delete_security_group(TEST_GROUP) | ||
786 | 420 | groups = self.conn.get_all_security_groups() | ||
787 | 421 | self.assertFalse(TEST_GROUP in [group.name for group in groups]) | ||
788 | 422 | self.conn.terminate_instances([self.data['instance_id']]) | ||
789 | 423 | self.assertTrue(self.conn.release_address(self.data['public_ip'])) | ||
790 | 424 | |||
791 | 425 | |||
792 | 426 | if __name__ == "__main__": | 288 | if __name__ == "__main__": |
793 | 427 | suites = {'image': unittest.makeSuite(ImageTests), | 289 | suites = {'image': unittest.makeSuite(ImageTests), |
794 | 428 | 'instance': unittest.makeSuite(InstanceTests), | 290 | 'instance': unittest.makeSuite(InstanceTests), |
795 | 429 | 'security_group': unittest.makeSuite(SecurityGroupTests), | ||
796 | 430 | 'volume': unittest.makeSuite(VolumeTests) | 291 | 'volume': unittest.makeSuite(VolumeTests) |
797 | 431 | } | 292 | } |
798 | 432 | sys.exit(base.run_tests(suites)) | 293 | sys.exit(base.run_tests(suites)) |
This is excellent refactoring, Vishy. Very impressed. Looking forward to your future cleanups. Now, let's get these running on some test machines from Hudson!