blob: c0d3f7ab747a90b496452c038cc79b9d7266aab5 [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
Masayuki Igawa259c1132013-10-31 17:48:44 +090016from tempest.common.utils import data_utils
Masayuki Igawa224a8272014-02-17 15:07:43 +090017from tempest.common.utils.linux import remote_client
Matthew Treinish88f49ef2014-01-29 18:36:27 +000018from tempest import config
Attila Fazekas234d3e82013-02-22 16:39:49 +010019from tempest import exceptions
Matthew Treinishf4a9b0f2013-07-26 16:58:26 -040020from tempest.openstack.common import log as logging
Masayuki Igawa224a8272014-02-17 15:07:43 +090021from tempest.thirdparty.boto import test as boto_test
22from tempest.thirdparty.boto.utils import s3
23from tempest.thirdparty.boto.utils import wait
Attila Fazekasa23f5002012-10-23 19:32:45 +020024
Matthew Treinish88f49ef2014-01-29 18:36:27 +000025CONF = config.CONF
26
Attila Fazekasa23f5002012-10-23 19:32:45 +020027LOG = logging.getLogger(__name__)
28
29
Masayuki Igawa224a8272014-02-17 15:07:43 +090030class InstanceRunTest(boto_test.BotoTestCase):
Attila Fazekasa23f5002012-10-23 19:32:45 +020031
32 @classmethod
33 def setUpClass(cls):
34 super(InstanceRunTest, cls).setUpClass()
Attila Fazekas234d3e82013-02-22 16:39:49 +010035 if not cls.conclusion['A_I_IMAGES_READY']:
ivan-zhu1feeb382013-01-24 10:14:39 +080036 raise cls.skipException("".join(("EC2 ", cls.__name__,
37 ": requires ami/aki/ari manifest")))
Attila Fazekasa23f5002012-10-23 19:32:45 +020038 cls.s3_client = cls.os.s3_client
39 cls.ec2_client = cls.os.ec2api_client
Attila Fazekas27dd92e2014-02-21 14:49:40 +010040 cls.zone = CONF.boto.aws_zone
Matthew Treinish88f49ef2014-01-29 18:36:27 +000041 cls.materials_path = CONF.boto.s3_materials_path
42 ami_manifest = CONF.boto.ami_manifest
43 aki_manifest = CONF.boto.aki_manifest
44 ari_manifest = CONF.boto.ari_manifest
45 cls.instance_type = CONF.boto.instance_type
Masayuki Igawa259c1132013-10-31 17:48:44 +090046 cls.bucket_name = data_utils.rand_name("s3bucket-")
47 cls.keypair_name = data_utils.rand_name("keypair-")
Attila Fazekasa23f5002012-10-23 19:32:45 +020048 cls.keypair = cls.ec2_client.create_key_pair(cls.keypair_name)
49 cls.addResourceCleanUp(cls.ec2_client.delete_key_pair,
50 cls.keypair_name)
51 bucket = cls.s3_client.create_bucket(cls.bucket_name)
52 cls.addResourceCleanUp(cls.destroy_bucket,
53 cls.s3_client.connection_data,
54 cls.bucket_name)
Masayuki Igawa224a8272014-02-17 15:07:43 +090055 s3.s3_upload_dir(bucket, cls.materials_path)
Attila Fazekasa23f5002012-10-23 19:32:45 +020056 cls.images = {"ami":
Masayuki Igawa259c1132013-10-31 17:48:44 +090057 {"name": data_utils.rand_name("ami-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020058 "location": cls.bucket_name + "/" + ami_manifest},
59 "aki":
Masayuki Igawa259c1132013-10-31 17:48:44 +090060 {"name": data_utils.rand_name("aki-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020061 "location": cls.bucket_name + "/" + aki_manifest},
62 "ari":
Masayuki Igawa259c1132013-10-31 17:48:44 +090063 {"name": data_utils.rand_name("ari-name-"),
Attila Fazekasa23f5002012-10-23 19:32:45 +020064 "location": cls.bucket_name + "/" + ari_manifest}}
65 for image in cls.images.itervalues():
66 image["image_id"] = cls.ec2_client.register_image(
Sean Dague14c68182013-04-14 15:34:30 -040067 name=image["name"],
68 image_location=image["location"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020069 cls.addResourceCleanUp(cls.ec2_client.deregister_image,
70 image["image_id"])
71
72 for image in cls.images.itervalues():
73 def _state():
74 retr = cls.ec2_client.get_image(image["image_id"])
75 return retr.state
Masayuki Igawa224a8272014-02-17 15:07:43 +090076 state = wait.state_wait(_state, "available")
Attila Fazekasa23f5002012-10-23 19:32:45 +020077 if state != "available":
78 for _image in cls.images.itervalues():
Attila Fazekasfa756cb2013-02-12 10:52:42 +010079 cls.ec2_client.deregister_image(_image["image_id"])
Matthew Treinish57160582014-06-09 17:13:48 -040080 raise exceptions.EC2RegisterImageException(
81 image_id=image["image_id"])
Attila Fazekasa23f5002012-10-23 19:32:45 +020082
Attila Fazekas1ec88152014-09-10 13:40:00 +020083 def _terminate_reservation(self, reservation, rcuk):
84 for instance in reservation.instances:
85 instance.terminate()
86 for instance in reservation.instances:
87 self.assertInstanceStateWait(instance, '_GONE')
88 self.cancelResourceCleanUp(rcuk)
89
Burt Holzmanf70f2222013-07-18 23:36:31 -050090 def test_run_idempotent_instances(self):
91 # EC2 run instances idempotently
92
93 def _run_instance(client_token):
94 reservation = self.ec2_client.run_instances(
95 image_id=self.images["ami"]["image_id"],
96 kernel_id=self.images["aki"]["image_id"],
97 ramdisk_id=self.images["ari"]["image_id"],
98 instance_type=self.instance_type,
99 client_token=client_token)
100 rcuk = self.addResourceCleanUp(self.destroy_reservation,
101 reservation)
102 return (reservation, rcuk)
103
Burt Holzmanf70f2222013-07-18 23:36:31 -0500104 reservation_1, rcuk_1 = _run_instance('token_1')
105 reservation_2, rcuk_2 = _run_instance('token_2')
106 reservation_1a, rcuk_1a = _run_instance('token_1')
107
108 self.assertIsNotNone(reservation_1)
109 self.assertIsNotNone(reservation_2)
110 self.assertIsNotNone(reservation_1a)
111
112 # same reservation for token_1
113 self.assertEqual(reservation_1.id, reservation_1a.id)
114
115 # Cancel cleanup -- since it's a duplicate, it's
116 # handled by rcuk1
117 self.cancelResourceCleanUp(rcuk_1a)
118
Attila Fazekas1ec88152014-09-10 13:40:00 +0200119 self._terminate_reservation(reservation_1, rcuk_1)
120 self._terminate_reservation(reservation_2, rcuk_2)
Burt Holzmanf70f2222013-07-18 23:36:31 -0500121
Attila Fazekasa23f5002012-10-23 19:32:45 +0200122 def test_run_stop_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500123 # EC2 run, stop and terminate instance
Attila Fazekasa23f5002012-10-23 19:32:45 +0200124 image_ami = self.ec2_client.get_image(self.images["ami"]
125 ["image_id"])
126 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
127 ramdisk_id=self.images["ari"]["image_id"],
128 instance_type=self.instance_type)
129 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
130
Attila Fazekasa23f5002012-10-23 19:32:45 +0200131 for instance in reservation.instances:
132 LOG.info("state: %s", instance.state)
133 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100134 self.assertInstanceStateWait(instance, "running")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200135
136 for instance in reservation.instances:
137 instance.stop()
138 LOG.info("state: %s", instance.state)
139 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100140 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200141
Attila Fazekas1ec88152014-09-10 13:40:00 +0200142 self._terminate_reservation(reservation, rcuk)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200143
Burt Holzmanbb575e12013-07-14 00:23:30 -0500144 def test_run_stop_terminate_instance_with_tags(self):
145 # EC2 run, stop and terminate instance with tags
146 image_ami = self.ec2_client.get_image(self.images["ami"]
147 ["image_id"])
148 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
149 ramdisk_id=self.images["ari"]["image_id"],
150 instance_type=self.instance_type)
151 rcuk = self.addResourceCleanUp(self.destroy_reservation, reservation)
152
153 for instance in reservation.instances:
154 LOG.info("state: %s", instance.state)
155 if instance.state != "running":
156 self.assertInstanceStateWait(instance, "running")
157 instance.add_tag('key1', value='value1')
158
159 tags = self.ec2_client.get_all_tags()
Chang Bo Guofc77e932013-09-16 17:38:26 -0700160 self.assertEqual(tags[0].name, 'key1')
161 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500162
163 tags = self.ec2_client.get_all_tags(filters={'key': 'key1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700164 self.assertEqual(tags[0].name, 'key1')
165 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500166
167 tags = self.ec2_client.get_all_tags(filters={'value': 'value1'})
Chang Bo Guofc77e932013-09-16 17:38:26 -0700168 self.assertEqual(tags[0].name, 'key1')
169 self.assertEqual(tags[0].value, 'value1')
Burt Holzmanbb575e12013-07-14 00:23:30 -0500170
171 tags = self.ec2_client.get_all_tags(filters={'key': 'value2'})
Attila Fazekas849708e2013-09-25 17:33:56 +0200172 self.assertEqual(len(tags), 0, str(tags))
Burt Holzmanbb575e12013-07-14 00:23:30 -0500173
174 for instance in reservation.instances:
175 instance.remove_tag('key1', value='value1')
176
177 tags = self.ec2_client.get_all_tags()
Rushi Agrawald0bea622014-07-07 17:57:08 +0530178
179 # NOTE: Volume-attach and detach causes metadata (tags) to be created
180 # for the volume. So exclude them while asserting.
181 self.assertNotIn('key1', tags)
Burt Holzmanbb575e12013-07-14 00:23:30 -0500182
183 for instance in reservation.instances:
184 instance.stop()
185 LOG.info("state: %s", instance.state)
186 if instance.state != "stopped":
187 self.assertInstanceStateWait(instance, "stopped")
188
Attila Fazekas1ec88152014-09-10 13:40:00 +0200189 self._terminate_reservation(reservation, rcuk)
Burt Holzmanbb575e12013-07-14 00:23:30 -0500190
Attila Fazekasa23f5002012-10-23 19:32:45 +0200191 def test_run_terminate_instance(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500192 # EC2 run, terminate immediately
Attila Fazekasa23f5002012-10-23 19:32:45 +0200193 image_ami = self.ec2_client.get_image(self.images["ami"]
194 ["image_id"])
195 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
196 ramdisk_id=self.images["ari"]["image_id"],
197 instance_type=self.instance_type)
198
199 for instance in reservation.instances:
200 instance.terminate()
Attila Fazekas1ec88152014-09-10 13:40:00 +0200201 self.assertInstanceStateWait(instance, '_GONE')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200202
Sean Dague3b563352014-04-22 20:00:46 -0400203 def test_compute_with_volumes(self):
Sean Dague64ef48d2013-01-03 17:54:36 -0500204 # EC2 1. integration test (not strict)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200205 image_ami = self.ec2_client.get_image(self.images["ami"]["image_id"])
Masayuki Igawa259c1132013-10-31 17:48:44 +0900206 sec_group_name = data_utils.rand_name("securitygroup-")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200207 group_desc = sec_group_name + " security group description "
208 security_group = self.ec2_client.create_security_group(sec_group_name,
209 group_desc)
210 self.addResourceCleanUp(self.destroy_security_group_wait,
211 security_group)
Sean Dague14c68182013-04-14 15:34:30 -0400212 self.assertTrue(
213 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030214 sec_group_name,
215 ip_protocol="icmp",
216 cidr_ip="0.0.0.0/0",
217 from_port=-1,
218 to_port=-1))
Sean Dague14c68182013-04-14 15:34:30 -0400219 self.assertTrue(
220 self.ec2_client.authorize_security_group(
Chris Yeoh86732f92013-02-27 20:52:06 +1030221 sec_group_name,
222 ip_protocol="tcp",
223 cidr_ip="0.0.0.0/0",
224 from_port=22,
225 to_port=22))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200226 reservation = image_ami.run(kernel_id=self.images["aki"]["image_id"],
227 ramdisk_id=self.images["ari"]["image_id"],
228 instance_type=self.instance_type,
229 key_name=self.keypair_name,
230 security_groups=(sec_group_name,))
Sean Dague3b563352014-04-22 20:00:46 -0400231
232 LOG.debug("Instance booted - state: %s",
233 reservation.instances[0].state)
234
Attila Fazekasa23f5002012-10-23 19:32:45 +0200235 self.addResourceCleanUp(self.destroy_reservation,
236 reservation)
237 volume = self.ec2_client.create_volume(1, self.zone)
Sean Dague3b563352014-04-22 20:00:46 -0400238 LOG.debug("Volume created - status: %s", volume.status)
239
Attila Fazekasa23f5002012-10-23 19:32:45 +0200240 self.addResourceCleanUp(self.destroy_volume_wait, volume)
241 instance = reservation.instances[0]
Attila Fazekasa23f5002012-10-23 19:32:45 +0200242 if instance.state != "running":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100243 self.assertInstanceStateWait(instance, "running")
Sean Dague3b563352014-04-22 20:00:46 -0400244 LOG.debug("Instance now running - state: %s", instance.state)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200245
246 address = self.ec2_client.allocate_address()
247 rcuk_a = self.addResourceCleanUp(address.delete)
Chris Yeoh86732f92013-02-27 20:52:06 +1030248 self.assertTrue(address.associate(instance.id))
Attila Fazekasa23f5002012-10-23 19:32:45 +0200249
250 rcuk_da = self.addResourceCleanUp(address.disassociate)
Attila Fazekas3e381f72013-08-01 16:52:23 +0200251 # TODO(afazekas): ping test. dependecy/permission ?
Attila Fazekasa23f5002012-10-23 19:32:45 +0200252
Attila Fazekas40aa3612013-01-19 22:16:38 +0100253 self.assertVolumeStatusWait(volume, "available")
Marc Solanasb15d8b62014-02-07 00:04:15 -0800254 # NOTE(afazekas): it may be reports available before it is available
Attila Fazekasa23f5002012-10-23 19:32:45 +0200255
Masayuki Igawa224a8272014-02-17 15:07:43 +0900256 ssh = remote_client.RemoteClient(address.public_ip,
257 CONF.compute.ssh_user,
258 pkey=self.keypair.material)
Masayuki Igawa259c1132013-10-31 17:48:44 +0900259 text = data_utils.rand_name("Pattern text for console output -")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200260 resp = ssh.write_to_console(text)
261 self.assertFalse(resp)
262
263 def _output():
264 output = instance.get_console_output()
265 return output.output
266
Masayuki Igawa224a8272014-02-17 15:07:43 +0900267 wait.re_search_wait(_output, text)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200268 part_lines = ssh.get_partitions().split('\n')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200269 volume.attach(instance.id, "/dev/vdh")
270
Attila Fazekas40aa3612013-01-19 22:16:38 +0100271 def _volume_state():
Sean Dague3b563352014-04-22 20:00:46 -0400272 """Return volume state realizing that 'in-use' is overloaded."""
Attila Fazekas40aa3612013-01-19 22:16:38 +0100273 volume.update(validate=True)
Sean Dague3b563352014-04-22 20:00:46 -0400274 status = volume.status
275 attached = volume.attach_data.status
276 LOG.debug("Volume %s is in status: %s, attach_status: %s",
277 volume.id, status, attached)
278 # Nova reports 'in-use' on 'attaching' volumes because we
279 # have a single volume status, and EC2 has 2. Ensure that
280 # if we aren't attached yet we return something other than
281 # 'in-use'
282 if status == 'in-use' and attached != 'attached':
283 return 'attaching'
284 else:
285 return status
Attila Fazekas40aa3612013-01-19 22:16:38 +0100286
Masayuki Igawa224a8272014-02-17 15:07:43 +0900287 wait.re_search_wait(_volume_state, "in-use")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200288
Attila Fazekas3e381f72013-08-01 16:52:23 +0200289 # NOTE(afazekas): Different Hypervisor backends names
Attila Fazekasa23f5002012-10-23 19:32:45 +0200290 # differently the devices,
291 # now we just test is the partition number increased/decrised
292
293 def _part_state():
294 current = ssh.get_partitions().split('\n')
Sean Dague3b563352014-04-22 20:00:46 -0400295 LOG.debug("Partition map for instance: %s", current)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200296 if current > part_lines:
297 return 'INCREASE'
298 if current < part_lines:
299 return 'DECREASE'
300 return 'EQUAL'
301
Masayuki Igawa224a8272014-02-17 15:07:43 +0900302 wait.state_wait(_part_state, 'INCREASE')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200303 part_lines = ssh.get_partitions().split('\n')
304
Attila Fazekas3e381f72013-08-01 16:52:23 +0200305 # TODO(afazekas): Resource compare to the flavor settings
Attila Fazekasa23f5002012-10-23 19:32:45 +0200306
Chris Yeohf2a5e822013-05-08 21:33:00 +0930307 volume.detach()
Attila Fazekasa23f5002012-10-23 19:32:45 +0200308
Chris Yeohf2a5e822013-05-08 21:33:00 +0930309 self.assertVolumeStatusWait(_volume_state, "available")
Masayuki Igawa224a8272014-02-17 15:07:43 +0900310 wait.re_search_wait(_volume_state, "available")
Attila Fazekasa23f5002012-10-23 19:32:45 +0200311
Masayuki Igawa224a8272014-02-17 15:07:43 +0900312 wait.state_wait(_part_state, 'DECREASE')
Attila Fazekasa23f5002012-10-23 19:32:45 +0200313
314 instance.stop()
315 address.disassociate()
316 self.assertAddressDissasociatedWait(address)
317 self.cancelResourceCleanUp(rcuk_da)
318 address.release()
319 self.assertAddressReleasedWait(address)
320 self.cancelResourceCleanUp(rcuk_a)
321
Sean Dague3b563352014-04-22 20:00:46 -0400322 LOG.debug("Instance %s state: %s", instance.id, instance.state)
Attila Fazekasa23f5002012-10-23 19:32:45 +0200323 if instance.state != "stopped":
Attila Fazekas40aa3612013-01-19 22:16:38 +0100324 self.assertInstanceStateWait(instance, "stopped")
Attila Fazekas3e381f72013-08-01 16:52:23 +0200325 # TODO(afazekas): move steps from teardown to the test case
Attila Fazekasa23f5002012-10-23 19:32:45 +0200326
327
Attila Fazekas3e381f72013-08-01 16:52:23 +0200328# TODO(afazekas): Snapshot/volume read/write test case