blob: 0f455e1ae8fa5083b9f02249b29001d7c76e6c16 [file] [log] [blame]
Attila Fazekasa23f5002012-10-23 19:32:45 +02001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
ZhiQiang Fan39f97222013-09-20 04:49:44 +08003# Copyright 2012 OpenStack Foundation
Attila Fazekasa23f5002012-10-23 19:32:45 +02004# All Rights Reserved.
5#
6# Licensed under the Apache License, Version 2.0 (the "License"); you may
7# not use this file except in compliance with the License. You may obtain
8# a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15# License for the specific language governing permissions and limitations
16# under the License.
17
Attila Fazekas234d3e82013-02-22 16:39:49 +010018from boto import exception
Matthew Treinisha83a16e2012-12-07 13:44:02 -050019
Matthew Treinish481466b2012-12-20 17:16:01 -050020from tempest import clients
Matthew Treinisha83a16e2012-12-07 13:44:02 -050021from tempest.common.utils.data_utils import rand_name
22from tempest.common.utils.linux.remote_client import RemoteClient
Attila Fazekas234d3e82013-02-22 16:39:49 +010023from tempest import exceptions
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040024from tempest.openstack.common import log as logging
Chris Yeoh01cb2792013-02-09 22:25:37 +103025from tempest.test import attr
Giulio Fidente83181a92013-10-01 06:02:24 +020026from tempest.test import skip_because
Sean Dague09761f62013-05-13 15:20:40 -040027from tempest.thirdparty.boto.test import BotoTestCase
28from tempest.thirdparty.boto.utils.s3 import s3_upload_dir
29from tempest.thirdparty.boto.utils.wait import re_search_wait
30from tempest.thirdparty.boto.utils.wait import state_wait
Attila Fazekasa23f5002012-10-23 19:32:45 +020031
32LOG = logging.getLogger(__name__)
33
34
Attila Fazekasa23f5002012-10-23 19:32:45 +020035class InstanceRunTest(BotoTestCase):
36
37 @classmethod
38 def setUpClass(cls):
39 super(InstanceRunTest, cls).setUpClass()
Attila Fazekas234d3e82013-02-22 16:39:49 +010040 if not cls.conclusion['A_I_IMAGES_READY']:
ivan-zhu1feeb382013-01-24 10:14:39 +080041 raise cls.skipException("".join(("EC2 ", cls.__name__,
42 ": requires ami/aki/ari manifest")))
Matthew Treinish481466b2012-12-20 17:16:01 -050043 cls.os = clients.Manager()
Attila Fazekasa23f5002012-10-23 19:32:45 +020044 cls.s3_client = cls.os.s3_client
45 cls.ec2_client = cls.os.ec2api_client
Attila Fazekasa23f5002012-10-23 19:32:45 +020046 cls.zone = cls.ec2_client.get_good_zone()
Attila Fazekasdc216422013-01-29 15:12:14 +010047 config = cls.config
Attila Fazekasa23f5002012-10-23 19:32:45 +020048 cls.materials_path = config.boto.s3_materials_path
49 ami_manifest = config.boto.ami_manifest
50 aki_manifest = config.boto.aki_manifest
51 ari_manifest = config.boto.ari_manifest
52 cls.instance_type = config.boto.instance_type
53 cls.bucket_name = rand_name("s3bucket-")
54 cls.keypair_name = rand_name("keypair-")
55 cls.keypair = cls.ec2_client.create_key_pair(cls.keypair_name)
56 cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
57 cls.keypair_name)
58 bucket = cls.s3_client.create_bucket(cls.bucket_name)
59 cls.addResourceCleanUp(cls.destroy_bucket,
60 cls.s3_client.connection_data,
61 cls.bucket_name)
62 s3_upload_dir(bucket, cls.materials_path)
63 cls.images = {"ami":
64 {"name": rand_name("ami-name-"),
65 "location": cls.bucket_name + "/" + ami_manifest},
66 "aki":
67 {"name": rand_name("aki-name-"),
68 "location": cls.bucket_name + "/" + aki_manifest},
69 "ari":
70 {"name": rand_name("ari-name-"),
71 "location": cls.bucket_name + "/" + ari_manifest}}
72 for image in cls.images.itervalues():
73 image["image_id"] = cls.ec2_client.register_image(
Sean Dague14c68182013-04-14 15:34:30 -040074 name=image["name"],
75 image_location=image["location"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020076 cls.addResourceCleanUp(cls.ec2_client.deregister_image,
77 image["image_id"])
78
79 for image in cls.images.itervalues():
80 def _state():
81 retr = cls.ec2_client.get_image(image["image_id"])
82 return retr.state
83 state = state_wait(_state, "available")
84 if state != "available":
85 for _image in cls.images.itervalues():
Attila Fazekasfa756cb2013-02-12 10:52:42 +010086 cls.ec2_client.deregister_image(_image["image_id"])
Attila Fazekas234d3e82013-02-22 16:39:49 +010087 raise exceptions.EC2RegisterImageException(image_id=
88 image["image_id"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020089
90 @attr(type='smoke')
Burt Holzmanf70f2222013-07-18 23:36:31 -050091 def test_run_idempotent_instances(self):
92 # EC2 run instances idempotently
93
94 def _run_instance(client_token):
95 reservation = self.ec2_client.run_instances(
96 image_id=self.images["ami"]["image_id"],
97 kernel_id=self.images["aki"]["image_id"],
98 ramdisk_id=self.images["ari"]["image_id"],
99 instance_type=self.instance_type,
100 client_token=client_token)
101 rcuk = self.addResourceCleanUp(self.destroy_reservation,
102 reservation)
103 return (reservation, rcuk)
104
105 def _terminate_reservation(reservation, rcuk):
106 for instance in reservation.instances:
107 instance.terminate()
108 self.cancelResourceCleanUp(rcuk)
109
110 reservation_1, rcuk_1 = _run_instance('token_1')
111 reservation_2, rcuk_2 = _run_instance('token_2')
112 reservation_1a, rcuk_1a = _run_instance('token_1')
113
114 self.assertIsNotNone(reservation_1)
115 self.assertIsNotNone(reservation_2)
116 self.assertIsNotNone(reservation_1a)
117
118 # same reservation for token_1
119 self.assertEqual(reservation_1.id, reservation_1a.id)
120
121 # Cancel cleanup -- since it's a duplicate, it's
122 # handled by rcuk1
123 self.cancelResourceCleanUp(rcuk_1a)
124
125 _terminate_reservation(reservation_1, rcuk_1)
126 _terminate_reservation(reservation_2, rcuk_2)
127
128 reservation_3, rcuk_3 = _run_instance('token_1')
129 self.assertIsNotNone(reservation_3)
130
131 # make sure we don't get the old reservation back
132 self.assertNotEqual(reservation_1.id, reservation_3.id)
133
134 # clean up
135 _terminate_reservation(reservation_3, rcuk_3)
136
137 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200138 def test_run_stop_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500139 # EC2 run, stop and terminate instance
Attila Fazekasa23f5002012-10-23 19:32:45 +0200140 image_ami = self.ec2_client.get_image(self.images["ami"]
141 ["image_id"])
142 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
143 ramdisk_id=self.images["ari"]["image_id"],
144 instance_type=self.instance_type)
145 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
146
Attila Fazekasa23f5002012-10-23 19:32:45 +0200147 for instance in reservation.instances:
148 LOG.info("state: %s", instance.state)
149 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100150 self.assertInstanceStateWait(instance, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200151
152 for instance in reservation.instances:
153 instance.stop()
154 LOG.info("state: %s", instance.state)
155 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100156 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200157
158 for instance in reservation.instances:
159 instance.terminate()
160 self.cancelResourceCleanUp(rcuk)
161
162 @attr(type='smoke')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500163 def test_run_stop_terminate_instance_with_tags(self):
164 # EC2 run, stop and terminate instance with tags
165 image_ami = self.ec2_client.get_image(self.images["ami"]
166 ["image_id"])
167 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
168 ramdisk_id=self.images["ari"]["image_id"],
169 instance_type=self.instance_type)
170 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
171
172 for instance in reservation.instances:
173 LOG.info("state: %s", instance.state)
174 if instance.state != "running":
175 self.assertInstanceStateWait(instance, "running")
176 instance.add_tag('key1', value='value1')
177
178 tags = self.ec2_client.get_all_tags()
Chang Bo Guofc77e932013-09-16 17:38:26 -0700179 self.assertEqual(tags[0].name, 'key1')
180 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500181
182 tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700183 self.assertEqual(tags[0].name, 'key1')
184 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500185
186 tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700187 self.assertEqual(tags[0].name, 'key1')
188 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500189
190 tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
Attila Fazekas849708e2013-09-25 17:33:56 +0200191 self.assertEqual(len(tags), 0, str(tags))
Burt Holzmanbb575e12013-07-14 00:23:30 -0500192
193 for instance in reservation.instances:
194 instance.remove_tag('key1', value='value1')
195
196 tags = self.ec2_client.get_all_tags()
Attila Fazekas849708e2013-09-25 17:33:56 +0200197 self.assertEqual(len(tags), 0, str(tags))
Burt Holzmanbb575e12013-07-14 00:23:30 -0500198
199 for instance in reservation.instances:
200 instance.stop()
201 LOG.info("state: %s", instance.state)
202 if instance.state != "stopped":
203 self.assertInstanceStateWait(instance, "stopped")
204
205 for instance in reservation.instances:
206 instance.terminate()
207 self.cancelResourceCleanUp(rcuk)
208
Giulio Fidente83181a92013-10-01 06:02:24 +0200209 @skip_because(bug="1098891")
Burt Holzmanbb575e12013-07-14 00:23:30 -0500210 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200211 def test_run_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500212 # EC2 run, terminate immediately
Attila Fazekasa23f5002012-10-23 19:32:45 +0200213 image_ami = self.ec2_client.get_image(self.images["ami"]
214 ["image_id"])
215 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
216 ramdisk_id=self.images["ari"]["image_id"],
217 instance_type=self.instance_type)
218
219 for instance in reservation.instances:
220 instance.terminate()
Attila Fazekas37f83042013-01-12 16:13:03 +0100221 try:
222 instance.update(validate=True)
223 except ValueError:
224 pass
Attila Fazekas234d3e82013-02-22 16:39:49 +0100225 except exception.EC2ResponseError as exc:
Attila Fazekas37f83042013-01-12 16:13:03 +0100226 if self.ec2_error_code.\
227 client.InvalidInstanceID.NotFound.match(exc):
228 pass
229 else:
230 raise
231 else:
232 self.assertNotEqual(instance.state, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200233
Attila Fazekas3e381f72013-08-01 16:52:23 +0200234 # NOTE(afazekas): doctored test case,
Attila Fazekasa23f5002012-10-23 19:32:45 +0200235 # with normal validation it would fail
Giulio Fidente83181a92013-10-01 06:02:24 +0200236 @skip_because(bug="1182679")
Giampaolo Lauriacb9209d2013-05-17 13:39:25 -0400237 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200238 def test_integration_1(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500239 # EC2 1. integration test (not strict)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200240 image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
241 sec_group_name = rand_name("securitygroup-")
242 group_desc = sec_group_name + " security group description "
243 security_group = self.ec2_client.create_security_group(sec_group_name,
244 group_desc)
245 self.addResourceCleanUp(self.destroy_security_group_wait,
246 security_group)
Sean Dague14c68182013-04-14 15:34:30 -0400247 self.assertTrue(
248 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030249 sec_group_name,
250 ip_protocol="icmp",
251 cidr_ip="0.0.0.0/0",
252 from_port=-1,
253 to_port=-1))
Sean Dague14c68182013-04-14 15:34:30 -0400254 self.assertTrue(
255 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030256 sec_group_name,
257 ip_protocol="tcp",
258 cidr_ip="0.0.0.0/0",
259 from_port=22,
260 to_port=22))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200261 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
262 ramdisk_id=self.images["ari"]["image_id"],
263 instance_type=self.instance_type,
264 key_name=self.keypair_name,
265 security_groups=(sec_group_name,))
266 self.addResourceCleanUp(self.destroy_reservation,
267 reservation)
268 volume = self.ec2_client.create_volume(1, self.zone)
269 self.addResourceCleanUp(self.destroy_volume_wait, volume)
270 instance = reservation.instances[0]
Attila Fazekasa23f5002012-10-23 19:32:45 +0200271 LOG.info("state: %s", instance.state)
272 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100273 self.assertInstanceStateWait(instance, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200274
275 address = self.ec2_client.allocate_address()
276 rcuk_a = self.addResourceCleanUp(address.delete)
Chris Yeoh86732f92013-02-27 20:52:06 +1030277 self.assertTrue(address.associate(instance.id))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200278
279 rcuk_da = self.addResourceCleanUp(address.disassociate)
Attila Fazekas3e381f72013-08-01 16:52:23 +0200280 # TODO(afazekas): ping test. dependecy/permission ?
Attila Fazekasa23f5002012-10-23 19:32:45 +0200281
Attila Fazekas40aa3612013-01-19 22:16:38 +0100282 self.assertVolumeStatusWait(volume, "available")
Attila Fazekas3e381f72013-08-01 16:52:23 +0200283 # NOTE(afazekas): it may be reports availble before it is available
Attila Fazekasa23f5002012-10-23 19:32:45 +0200284
285 ssh = RemoteClient(address.public_ip,
286 self.os.config.compute.ssh_user,
287 pkey=self.keypair.material)
288 text = rand_name("Pattern text for console output -")
289 resp = ssh.write_to_console(text)
290 self.assertFalse(resp)
291
292 def _output():
293 output = instance.get_console_output()
294 return output.output
295
296 re_search_wait(_output, text)
297 part_lines = ssh.get_partitions().split('\n')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200298 volume.attach(instance.id, "/dev/vdh")
299
Attila Fazekas40aa3612013-01-19 22:16:38 +0100300 def _volume_state():
301 volume.update(validate=True)
302 return volume.status
303
Chris Yeohf2a5e822013-05-08 21:33:00 +0930304 self.assertVolumeStatusWait(_volume_state, "in-use")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200305 re_search_wait(_volume_state, "in-use")
306
Attila Fazekas3e381f72013-08-01 16:52:23 +0200307 # NOTE(afazekas): Different Hypervisor backends names
Attila Fazekasa23f5002012-10-23 19:32:45 +0200308 # differently the devices,
309 # now we just test is the partition number increased/decrised
310
311 def _part_state():
312 current = ssh.get_partitions().split('\n')
313 if current > part_lines:
314 return 'INCREASE'
315 if current < part_lines:
316 return 'DECREASE'
317 return 'EQUAL'
318
319 state_wait(_part_state, 'INCREASE')
320 part_lines = ssh.get_partitions().split('\n')
321
Attila Fazekas3e381f72013-08-01 16:52:23 +0200322 # TODO(afazekas): Resource compare to the flavor settings
Attila Fazekasa23f5002012-10-23 19:32:45 +0200323
Chris Yeohf2a5e822013-05-08 21:33:00 +0930324 volume.detach()
Attila Fazekasa23f5002012-10-23 19:32:45 +0200325
Chris Yeohf2a5e822013-05-08 21:33:00 +0930326 self.assertVolumeStatusWait(_volume_state, "available")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200327 re_search_wait(_volume_state, "available")
328 LOG.info("Volume %s state: %s", volume.id, volume.status)
329
330 state_wait(_part_state, 'DECREASE')
331
332 instance.stop()
333 address.disassociate()
334 self.assertAddressDissasociatedWait(address)
335 self.cancelResourceCleanUp(rcuk_da)
336 address.release()
337 self.assertAddressReleasedWait(address)
338 self.cancelResourceCleanUp(rcuk_a)
339
340 LOG.info("state: %s", instance.state)
341 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100342 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekas3e381f72013-08-01 16:52:23 +0200343 # TODO(afazekas): move steps from teardown to the test case
Attila Fazekasa23f5002012-10-23 19:32:45 +0200344
345
Attila Fazekas3e381f72013-08-01 16:52:23 +0200346# TODO(afazekas): Snapshot/volume read/write test case