blob: 399a3c89ea2baa6d1981cb2af5fdf917508c2eb8 [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Attila Fazekasa23f5002012-10-23 19:32:45 +02002# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Attila Fazekas234d3e82013-02-22 16:39:49 +010016from boto import exception
Matthew Treinisha83a16e2012-12-07 13:44:02 -050017
Masayuki Igawa259c1132013-10-31 17:48:44 +090018from tempest.common.utils import data_utils
Matthew Treinisha83a16e2012-12-07 13:44:02 -050019from tempest.common.utils.linux.remote_client import RemoteClient
Matthew Treinish88f49ef2014-01-29 18:36:27 +000020from tempest import config
Attila Fazekas234d3e82013-02-22 16:39:49 +010021from tempest import exceptions
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040022from tempest.openstack.common import log as logging
Chris Yeoh01cb2792013-02-09 22:25:37 +103023from tempest.test import attr
Giulio Fidente83181a92013-10-01 06:02:24 +020024from tempest.test import skip_because
Sean Dague09761f62013-05-13 15:20:40 -040025from tempest.thirdparty.boto.test import BotoTestCase
26from tempest.thirdparty.boto.utils.s3 import s3_upload_dir
27from tempest.thirdparty.boto.utils.wait import re_search_wait
28from tempest.thirdparty.boto.utils.wait import state_wait
Attila Fazekasa23f5002012-10-23 19:32:45 +020029
Matthew Treinish88f49ef2014-01-29 18:36:27 +000030CONF = config.CONF
31
Attila Fazekasa23f5002012-10-23 19:32:45 +020032LOG = 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")))
Attila Fazekasa23f5002012-10-23 19:32:45 +020043 cls.s3_client = cls.os.s3_client
44 cls.ec2_client = cls.os.ec2api_client
Attila Fazekasa23f5002012-10-23 19:32:45 +020045 cls.zone = cls.ec2_client.get_good_zone()
Matthew Treinish88f49ef2014-01-29 18:36:27 +000046 cls.materials_path = CONF.boto.s3_materials_path
47 ami_manifest = CONF.boto.ami_manifest
48 aki_manifest = CONF.boto.aki_manifest
49 ari_manifest = CONF.boto.ari_manifest
50 cls.instance_type = CONF.boto.instance_type
Masayuki Igawa259c1132013-10-31 17:48:44 +090051 cls.bucket_name = data_utils.rand_name("s3bucket-")
52 cls.keypair_name = data_utils.rand_name("keypair-")
Attila Fazekasa23f5002012-10-23 19:32:45 +020053 cls.keypair = cls.ec2_client.create_key_pair(cls.keypair_name)
54 cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
55 cls.keypair_name)
56 bucket = cls.s3_client.create_bucket(cls.bucket_name)
57 cls.addResourceCleanUp(cls.destroy_bucket,
58 cls.s3_client.connection_data,
59 cls.bucket_name)
60 s3_upload_dir(bucket, cls.materials_path)
61 cls.images = {"ami":
Masayuki Igawa259c1132013-10-31 17:48:44 +090062 {"name": data_utils.rand_name("ami-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020063 "location": cls.bucket_name + "/" + ami_manifest},
64 "aki":
Masayuki Igawa259c1132013-10-31 17:48:44 +090065 {"name": data_utils.rand_name("aki-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020066 "location": cls.bucket_name + "/" + aki_manifest},
67 "ari":
Masayuki Igawa259c1132013-10-31 17:48:44 +090068 {"name": data_utils.rand_name("ari-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020069 "location": cls.bucket_name + "/" + ari_manifest}}
70 for image in cls.images.itervalues():
71 image["image_id"] = cls.ec2_client.register_image(
Sean Dague14c68182013-04-14 15:34:30 -040072 name=image["name"],
73 image_location=image["location"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020074 cls.addResourceCleanUp(cls.ec2_client.deregister_image,
75 image["image_id"])
76
77 for image in cls.images.itervalues():
78 def _state():
79 retr = cls.ec2_client.get_image(image["image_id"])
80 return retr.state
81 state = state_wait(_state, "available")
82 if state != "available":
83 for _image in cls.images.itervalues():
Attila Fazekasfa756cb2013-02-12 10:52:42 +010084 cls.ec2_client.deregister_image(_image["image_id"])
Attila Fazekas234d3e82013-02-22 16:39:49 +010085 raise exceptions.EC2RegisterImageException(image_id=
86 image["image_id"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020087
88 @attr(type='smoke')
Burt Holzmanf70f2222013-07-18 23:36:31 -050089 def test_run_idempotent_instances(self):
90 # EC2 run instances idempotently
91
92 def _run_instance(client_token):
93 reservation = self.ec2_client.run_instances(
94 image_id=self.images["ami"]["image_id"],
95 kernel_id=self.images["aki"]["image_id"],
96 ramdisk_id=self.images["ari"]["image_id"],
97 instance_type=self.instance_type,
98 client_token=client_token)
99 rcuk = self.addResourceCleanUp(self.destroy_reservation,
100 reservation)
101 return (reservation, rcuk)
102
103 def _terminate_reservation(reservation, rcuk):
104 for instance in reservation.instances:
105 instance.terminate()
106 self.cancelResourceCleanUp(rcuk)
107
108 reservation_1, rcuk_1 = _run_instance('token_1')
109 reservation_2, rcuk_2 = _run_instance('token_2')
110 reservation_1a, rcuk_1a = _run_instance('token_1')
111
112 self.assertIsNotNone(reservation_1)
113 self.assertIsNotNone(reservation_2)
114 self.assertIsNotNone(reservation_1a)
115
116 # same reservation for token_1
117 self.assertEqual(reservation_1.id, reservation_1a.id)
118
119 # Cancel cleanup -- since it's a duplicate, it's
120 # handled by rcuk1
121 self.cancelResourceCleanUp(rcuk_1a)
122
123 _terminate_reservation(reservation_1, rcuk_1)
124 _terminate_reservation(reservation_2, rcuk_2)
125
126 reservation_3, rcuk_3 = _run_instance('token_1')
127 self.assertIsNotNone(reservation_3)
128
129 # make sure we don't get the old reservation back
130 self.assertNotEqual(reservation_1.id, reservation_3.id)
131
132 # clean up
133 _terminate_reservation(reservation_3, rcuk_3)
134
135 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200136 def test_run_stop_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500137 # EC2 run, stop and terminate instance
Attila Fazekasa23f5002012-10-23 19:32:45 +0200138 image_ami = self.ec2_client.get_image(self.images["ami"]
139 ["image_id"])
140 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
141 ramdisk_id=self.images["ari"]["image_id"],
142 instance_type=self.instance_type)
143 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
144
Attila Fazekasa23f5002012-10-23 19:32:45 +0200145 for instance in reservation.instances:
146 LOG.info("state: %s", instance.state)
147 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100148 self.assertInstanceStateWait(instance, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200149
150 for instance in reservation.instances:
151 instance.stop()
152 LOG.info("state: %s", instance.state)
153 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100154 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200155
156 for instance in reservation.instances:
157 instance.terminate()
158 self.cancelResourceCleanUp(rcuk)
159
160 @attr(type='smoke')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500161 def test_run_stop_terminate_instance_with_tags(self):
162 # EC2 run, stop and terminate instance with tags
163 image_ami = self.ec2_client.get_image(self.images["ami"]
164 ["image_id"])
165 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
166 ramdisk_id=self.images["ari"]["image_id"],
167 instance_type=self.instance_type)
168 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
169
170 for instance in reservation.instances:
171 LOG.info("state: %s", instance.state)
172 if instance.state != "running":
173 self.assertInstanceStateWait(instance, "running")
174 instance.add_tag('key1', value='value1')
175
176 tags = self.ec2_client.get_all_tags()
Chang Bo Guofc77e932013-09-16 17:38:26 -0700177 self.assertEqual(tags[0].name, 'key1')
178 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500179
180 tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700181 self.assertEqual(tags[0].name, 'key1')
182 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500183
184 tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700185 self.assertEqual(tags[0].name, 'key1')
186 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500187
188 tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
Attila Fazekas849708e2013-09-25 17:33:56 +0200189 self.assertEqual(len(tags), 0, str(tags))
Burt Holzmanbb575e12013-07-14 00:23:30 -0500190
191 for instance in reservation.instances:
192 instance.remove_tag('key1', value='value1')
193
194 tags = self.ec2_client.get_all_tags()
Attila Fazekas849708e2013-09-25 17:33:56 +0200195 self.assertEqual(len(tags), 0, str(tags))
Burt Holzmanbb575e12013-07-14 00:23:30 -0500196
197 for instance in reservation.instances:
198 instance.stop()
199 LOG.info("state: %s", instance.state)
200 if instance.state != "stopped":
201 self.assertInstanceStateWait(instance, "stopped")
202
203 for instance in reservation.instances:
204 instance.terminate()
205 self.cancelResourceCleanUp(rcuk)
206
Giulio Fidente83181a92013-10-01 06:02:24 +0200207 @skip_because(bug="1098891")
Burt Holzmanbb575e12013-07-14 00:23:30 -0500208 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200209 def test_run_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500210 # EC2 run, terminate immediately
Attila Fazekasa23f5002012-10-23 19:32:45 +0200211 image_ami = self.ec2_client.get_image(self.images["ami"]
212 ["image_id"])
213 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
214 ramdisk_id=self.images["ari"]["image_id"],
215 instance_type=self.instance_type)
216
217 for instance in reservation.instances:
218 instance.terminate()
Attila Fazekas37f83042013-01-12 16:13:03 +0100219 try:
220 instance.update(validate=True)
221 except ValueError:
222 pass
Attila Fazekas234d3e82013-02-22 16:39:49 +0100223 except exception.EC2ResponseError as exc:
Attila Fazekas37f83042013-01-12 16:13:03 +0100224 if self.ec2_error_code.\
225 client.InvalidInstanceID.NotFound.match(exc):
226 pass
227 else:
228 raise
229 else:
230 self.assertNotEqual(instance.state, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200231
Attila Fazekas3e381f72013-08-01 16:52:23 +0200232 # NOTE(afazekas): doctored test case,
Attila Fazekasa23f5002012-10-23 19:32:45 +0200233 # with normal validation it would fail
Giulio Fidente83181a92013-10-01 06:02:24 +0200234 @skip_because(bug="1182679")
Giampaolo Lauriacb9209d2013-05-17 13:39:25 -0400235 @attr(type='smoke')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200236 def test_integration_1(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500237 # EC2 1. integration test (not strict)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200238 image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
Masayuki Igawa259c1132013-10-31 17:48:44 +0900239 sec_group_name = data_utils.rand_name("securitygroup-")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200240 group_desc = sec_group_name + " security group description "
241 security_group = self.ec2_client.create_security_group(sec_group_name,
242 group_desc)
243 self.addResourceCleanUp(self.destroy_security_group_wait,
244 security_group)
Sean Dague14c68182013-04-14 15:34:30 -0400245 self.assertTrue(
246 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030247 sec_group_name,
248 ip_protocol="icmp",
249 cidr_ip="0.0.0.0/0",
250 from_port=-1,
251 to_port=-1))
Sean Dague14c68182013-04-14 15:34:30 -0400252 self.assertTrue(
253 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030254 sec_group_name,
255 ip_protocol="tcp",
256 cidr_ip="0.0.0.0/0",
257 from_port=22,
258 to_port=22))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200259 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
260 ramdisk_id=self.images["ari"]["image_id"],
261 instance_type=self.instance_type,
262 key_name=self.keypair_name,
263 security_groups=(sec_group_name,))
264 self.addResourceCleanUp(self.destroy_reservation,
265 reservation)
266 volume = self.ec2_client.create_volume(1, self.zone)
267 self.addResourceCleanUp(self.destroy_volume_wait, volume)
268 instance = reservation.instances[0]
Attila Fazekasa23f5002012-10-23 19:32:45 +0200269 LOG.info("state: %s", instance.state)
270 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100271 self.assertInstanceStateWait(instance, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200272
273 address = self.ec2_client.allocate_address()
274 rcuk_a = self.addResourceCleanUp(address.delete)
Chris Yeoh86732f92013-02-27 20:52:06 +1030275 self.assertTrue(address.associate(instance.id))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200276
277 rcuk_da = self.addResourceCleanUp(address.disassociate)
Attila Fazekas3e381f72013-08-01 16:52:23 +0200278 # TODO(afazekas): ping test. dependecy/permission ?
Attila Fazekasa23f5002012-10-23 19:32:45 +0200279
Attila Fazekas40aa3612013-01-19 22:16:38 +0100280 self.assertVolumeStatusWait(volume, "available")
Marc Solanasb15d8b62014-02-07 00:04:15 -0800281 # NOTE(afazekas): it may be reports available before it is available
Attila Fazekasa23f5002012-10-23 19:32:45 +0200282
283 ssh = RemoteClient(address.public_ip,
Matthew Treinish88f49ef2014-01-29 18:36:27 +0000284 CONF.compute.ssh_user,
Attila Fazekasa23f5002012-10-23 19:32:45 +0200285 pkey=self.keypair.material)
Masayuki Igawa259c1132013-10-31 17:48:44 +0900286 text = data_utils.rand_name("Pattern text for console output -")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200287 resp = ssh.write_to_console(text)
288 self.assertFalse(resp)
289
290 def _output():
291 output = instance.get_console_output()
292 return output.output
293
294 re_search_wait(_output, text)
295 part_lines = ssh.get_partitions().split('\n')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200296 volume.attach(instance.id, "/dev/vdh")
297
Attila Fazekas40aa3612013-01-19 22:16:38 +0100298 def _volume_state():
299 volume.update(validate=True)
300 return volume.status
301
Chris Yeohf2a5e822013-05-08 21:33:00 +0930302 self.assertVolumeStatusWait(_volume_state, "in-use")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200303 re_search_wait(_volume_state, "in-use")
304
Attila Fazekas3e381f72013-08-01 16:52:23 +0200305 # NOTE(afazekas): Different Hypervisor backends names
Attila Fazekasa23f5002012-10-23 19:32:45 +0200306 # differently the devices,
307 # now we just test is the partition number increased/decrised
308
309 def _part_state():
310 current = ssh.get_partitions().split('\n')
311 if current > part_lines:
312 return 'INCREASE'
313 if current < part_lines:
314 return 'DECREASE'
315 return 'EQUAL'
316
317 state_wait(_part_state, 'INCREASE')
318 part_lines = ssh.get_partitions().split('\n')
319
Attila Fazekas3e381f72013-08-01 16:52:23 +0200320 # TODO(afazekas): Resource compare to the flavor settings
Attila Fazekasa23f5002012-10-23 19:32:45 +0200321
Chris Yeohf2a5e822013-05-08 21:33:00 +0930322 volume.detach()
Attila Fazekasa23f5002012-10-23 19:32:45 +0200323
Chris Yeohf2a5e822013-05-08 21:33:00 +0930324 self.assertVolumeStatusWait(_volume_state, "available")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200325 re_search_wait(_volume_state, "available")
326 LOG.info("Volume %s state: %s", volume.id, volume.status)
327
328 state_wait(_part_state, 'DECREASE')
329
330 instance.stop()
331 address.disassociate()
332 self.assertAddressDissasociatedWait(address)
333 self.cancelResourceCleanUp(rcuk_da)
334 address.release()
335 self.assertAddressReleasedWait(address)
336 self.cancelResourceCleanUp(rcuk_a)
337
338 LOG.info("state: %s", instance.state)
339 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100340 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekas3e381f72013-08-01 16:52:23 +0200341 # TODO(afazekas): move steps from teardown to the test case
Attila Fazekasa23f5002012-10-23 19:32:45 +0200342
343
Attila Fazekas3e381f72013-08-01 16:52:23 +0200344# TODO(afazekas): Snapshot/volume read/write test case