blob: cad22f3d9122cbbee27801721817fe99e56b4edd [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2012 OpenStack Foundation
Jay Pipes50677282012-01-06 15:39:20 -05002# 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
Matthew Treinishb0c65f22015-04-23 09:09:41 -040016from six import moves
Matthew Treinish01472ff2015-02-20 17:26:52 -050017
Sean Dague1937d092013-05-17 16:36:38 -040018from tempest.api.image import base
Fei Long Wangd39431f2015-05-14 11:30:48 +120019from tempest.common.utils import data_utils
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000020from tempest import config
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090021from tempest import exceptions
ivan-zhud1bbe5d2013-12-29 18:32:46 +080022from tempest import test
Jay Pipes50677282012-01-06 15:39:20 -050023
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000024CONF = config.CONF
25
Jay Pipes50677282012-01-06 15:39:20 -050026
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090027def get_container_and_disk_format():
28 a_formats = ['ami', 'ari', 'aki']
29
30 container_format = CONF.image.container_formats[0]
31 disk_format = CONF.image.disk_formats[0]
32
33 if container_format in a_formats and container_format != disk_format:
34 msg = ("The container format and the disk format don't match. "
zhuflc35b36e2016-05-12 10:16:07 +080035 "Container format: %(container)s, Disk format: %(disk)s." %
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090036 {'container': container_format, 'disk': disk_format})
37 raise exceptions.InvalidConfiguration(message=msg)
38
39 return container_format, disk_format
40
41
Matthew Treinishce3ef922013-03-11 14:02:46 -040042class CreateRegisterImagesTest(base.BaseV1ImageTest):
43 """Here we test the registration and creation of images."""
Jay Pipes50677282012-01-06 15:39:20 -050044
Chris Hoge7579c1a2015-02-26 14:12:15 -080045 @test.idempotent_id('3027f8e6-3492-4a11-8575-c3293017af4d')
Jay Pipes50677282012-01-06 15:39:20 -050046 def test_register_then_upload(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050047 # Register, then upload an image
Matthew Treinish72ea4422013-02-07 14:42:49 -050048 properties = {'prop1': 'val1'}
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090049 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050050 body = self.create_image(name='New Name',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090051 container_format=container_format,
52 disk_format=disk_format,
David Kranz34f18782015-01-06 13:43:55 -050053 is_public=False,
54 properties=properties)
Attila Fazekase191cb12013-07-29 06:41:52 +020055 self.assertIn('id', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050056 image_id = body.get('id')
Matthew Treinish72ea4422013-02-07 14:42:49 -050057 self.assertEqual('New Name', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070058 self.assertFalse(body.get('is_public'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050059 self.assertEqual('queued', body.get('status'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050060 for key, val in properties.items():
61 self.assertEqual(val, body.get('properties')[key])
Jay Pipes50677282012-01-06 15:39:20 -050062
63 # Now try uploading an image file
Matthew Treinishb0c65f22015-04-23 09:09:41 -040064 image_file = moves.cStringIO(data_utils.random_bytes())
John Warren66207252015-07-31 15:51:02 -040065 body = self.client.update_image(image_id, data=image_file)['image']
Attila Fazekase191cb12013-07-29 06:41:52 +020066 self.assertIn('size', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050067 self.assertEqual(1024, body.get('size'))
Jay Pipes50677282012-01-06 15:39:20 -050068
Chris Hoge7579c1a2015-02-26 14:12:15 -080069 @test.idempotent_id('69da74d9-68a9-404b-9664-ff7164ccb0f5')
Jay Pipes50677282012-01-06 15:39:20 -050070 def test_register_remote_image(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050071 # Register a new remote image
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090072 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050073 body = self.create_image(name='New Remote Image',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090074 container_format=container_format,
75 disk_format=disk_format, is_public=False,
David Kranz34f18782015-01-06 13:43:55 -050076 location=CONF.image.http_image,
77 properties={'key1': 'value1',
78 'key2': 'value2'})
Attila Fazekase191cb12013-07-29 06:41:52 +020079 self.assertIn('id', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050080 self.assertEqual('New Remote Image', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070081 self.assertFalse(body.get('is_public'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050082 self.assertEqual('active', body.get('status'))
afazekas4a96bf82013-03-25 16:07:38 +010083 properties = body.get('properties')
84 self.assertEqual(properties['key1'], 'value1')
85 self.assertEqual(properties['key2'], 'value2')
Jay Pipes50677282012-01-06 15:39:20 -050086
Chris Hoge7579c1a2015-02-26 14:12:15 -080087 @test.idempotent_id('6d0e13a7-515b-460c-b91f-9f4793f09816')
Attila Fazekase72b7cd2013-03-26 18:34:21 +010088 def test_register_http_image(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090089 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050090 body = self.create_image(name='New Http Image',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090091 container_format=container_format,
92 disk_format=disk_format, is_public=False,
David Kranz34f18782015-01-06 13:43:55 -050093 copy_from=CONF.image.http_image)
Attila Fazekase191cb12013-07-29 06:41:52 +020094 self.assertIn('id', body)
Attila Fazekase72b7cd2013-03-26 18:34:21 +010095 image_id = body.get('id')
Attila Fazekase72b7cd2013-03-26 18:34:21 +010096 self.assertEqual('New Http Image', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070097 self.assertFalse(body.get('is_public'))
Attila Fazekase72b7cd2013-03-26 18:34:21 +010098 self.client.wait_for_image_status(image_id, 'active')
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +000099 self.client.show_image(image_id)
Attila Fazekase72b7cd2013-03-26 18:34:21 +0100100
Chris Hoge7579c1a2015-02-26 14:12:15 -0800101 @test.idempotent_id('05b19d55-140c-40d0-b36b-fafd774d421b')
hi2suresh75a20302013-04-09 09:17:06 +0000102 def test_register_image_with_min_ram(self):
103 # Register an image with min ram
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900104 container_format, disk_format = get_container_and_disk_format()
hi2suresh75a20302013-04-09 09:17:06 +0000105 properties = {'prop1': 'val1'}
David Kranz34f18782015-01-06 13:43:55 -0500106 body = self.create_image(name='New_image_with_min_ram',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900107 container_format=container_format,
108 disk_format=disk_format,
David Kranz34f18782015-01-06 13:43:55 -0500109 is_public=False,
110 min_ram=40,
111 properties=properties)
Attila Fazekase191cb12013-07-29 06:41:52 +0200112 self.assertIn('id', body)
hi2suresh75a20302013-04-09 09:17:06 +0000113 self.assertEqual('New_image_with_min_ram', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -0700114 self.assertFalse(body.get('is_public'))
hi2suresh75a20302013-04-09 09:17:06 +0000115 self.assertEqual('queued', body.get('status'))
116 self.assertEqual(40, body.get('min_ram'))
117 for key, val in properties.items():
118 self.assertEqual(val, body.get('properties')[key])
David Kranz9c3b3b62014-06-19 16:05:53 -0400119 self.client.delete_image(body['id'])
hi2suresh75a20302013-04-09 09:17:06 +0000120
Jay Pipes50677282012-01-06 15:39:20 -0500121
Matthew Treinishce3ef922013-03-11 14:02:46 -0400122class ListImagesTest(base.BaseV1ImageTest):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000123 """Here we test the listing of image information"""
Jay Pipes50677282012-01-06 15:39:20 -0500124
125 @classmethod
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900126 def skip_checks(cls):
127 super(ListImagesTest, cls).skip_checks()
128 if (len(CONF.image.container_formats) < 2
129 or len(CONF.image.disk_formats) < 2):
130 skip_msg = ("%s skipped as multiple container formats "
131 "or disk formats are not available." % cls.__name__)
132 raise cls.skipException(skip_msg)
133
134 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100135 def resource_setup(cls):
136 super(ListImagesTest, cls).resource_setup()
Jay Pipes50677282012-01-06 15:39:20 -0500137 # We add a few images here to test the listing functionality of
138 # the images API
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900139 a_formats = ['ami', 'ari', 'aki']
140
141 (cls.container_format,
142 cls.container_format_alt) = CONF.image.container_formats[:2]
143 cls.disk_format, cls.disk_format_alt = CONF.image.disk_formats[:2]
144 if cls.container_format in a_formats:
145 cls.disk_format = cls.container_format
146 if cls.container_format_alt in a_formats:
147 cls.disk_format_alt = cls.container_format_alt
148
149 img1 = cls._create_remote_image('one', cls.container_format,
150 cls.disk_format)
151 img2 = cls._create_remote_image('two', cls.container_format_alt,
152 cls.disk_format_alt)
153 img3 = cls._create_remote_image('dup', cls.container_format,
154 cls.disk_format)
155 img4 = cls._create_remote_image('dup', cls.container_format,
156 cls.disk_format)
157 img5 = cls._create_standard_image('1', cls.container_format_alt,
158 cls.disk_format_alt, 42)
159 img6 = cls._create_standard_image('2', cls.container_format_alt,
160 cls.disk_format_alt, 142)
161 img7 = cls._create_standard_image('33', cls.container_format,
162 cls.disk_format, 142)
163 img8 = cls._create_standard_image('33', cls.container_format,
164 cls.disk_format, 142)
Attila Fazekas11795b52013-02-24 15:49:08 +0100165 cls.created_set = set(cls.created_images)
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900166 # same container format
167 cls.same_container_format_set = set((img1, img3, img4, img7, img8))
168 # same disk format
169 cls.same_disk_format_set = set((img2, img5, img6))
170
Attila Fazekas11795b52013-02-24 15:49:08 +0100171 # 1x with size 42
172 cls.size42_set = set((img5,))
173 # 3x with size 142
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800174 cls.size142_set = set((img6, img7, img8,))
Attila Fazekas11795b52013-02-24 15:49:08 +0100175 # dup named
176 cls.dup_set = set((img3, img4))
Jay Pipes50677282012-01-06 15:39:20 -0500177
178 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100179 def _create_remote_image(cls, name, container_format, disk_format):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000180 """Create a new remote image and return newly-registered image-id"""
181
Attila Fazekas11795b52013-02-24 15:49:08 +0100182 name = 'New Remote Image %s' % name
Matthew Treinishe81ae692014-06-19 17:41:31 -0400183 location = CONF.image.http_image
David Kranz34f18782015-01-06 13:43:55 -0500184 image = cls.create_image(name=name,
185 container_format=container_format,
186 disk_format=disk_format,
187 is_public=False,
188 location=location)
Attila Fazekas11795b52013-02-24 15:49:08 +0100189 image_id = image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500190 return image_id
191
192 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100193 def _create_standard_image(cls, name, container_format,
194 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000195 """Create a new standard image and return newly-registered image-id
196
197 Note that the size of the new image is a random number between
Jay Pipes50677282012-01-06 15:39:20 -0500198 1024 and 4096
199 """
Matthew Treinishb0c65f22015-04-23 09:09:41 -0400200 image_file = moves.cStringIO(data_utils.random_bytes(size))
Attila Fazekas11795b52013-02-24 15:49:08 +0100201 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500202 image = cls.create_image(name=name,
203 container_format=container_format,
204 disk_format=disk_format,
205 is_public=False, data=image_file)
Attila Fazekas11795b52013-02-24 15:49:08 +0100206 image_id = image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500207 return image_id
208
Chris Hoge7579c1a2015-02-26 14:12:15 -0800209 @test.idempotent_id('246178ab-3b33-4212-9a4b-a7fe8261794d')
Jay Pipes50677282012-01-06 15:39:20 -0500210 def test_index_no_params(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -0500211 # Simple test to see all fixture images returned
John Warren66207252015-07-31 15:51:02 -0400212 images_list = self.client.list_images()['images']
Matthew Treinish72ea4422013-02-07 14:42:49 -0500213 image_list = map(lambda x: x['id'], images_list)
Attila Fazekas11795b52013-02-24 15:49:08 +0100214 for image_id in self.created_images:
Attila Fazekase191cb12013-07-29 06:41:52 +0200215 self.assertIn(image_id, image_list)
Attila Fazekas11795b52013-02-24 15:49:08 +0100216
Chris Hoge7579c1a2015-02-26 14:12:15 -0800217 @test.idempotent_id('f1755589-63d6-4468-b098-589820eb4031')
Attila Fazekas11795b52013-02-24 15:49:08 +0100218 def test_index_disk_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900219 images_list = self.client.list_images(
220 disk_format=self.disk_format_alt)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100221 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900222 self.assertEqual(image['disk_format'], self.disk_format_alt)
Attila Fazekas11795b52013-02-24 15:49:08 +0100223 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900224 self.assertTrue(self.same_disk_format_set <= result_set)
225 self.assertFalse(self.created_set - self.same_disk_format_set
226 <= result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100227
Chris Hoge7579c1a2015-02-26 14:12:15 -0800228 @test.idempotent_id('2143655d-96d9-4bec-9188-8674206b4b3b')
Attila Fazekas11795b52013-02-24 15:49:08 +0100229 def test_index_container_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900230 images_list = self.client.list_images(
231 container_format=self.container_format)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100232 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900233 self.assertEqual(image['container_format'], self.container_format)
Attila Fazekas11795b52013-02-24 15:49:08 +0100234 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900235 self.assertTrue(self.same_container_format_set <= result_set)
236 self.assertFalse(self.created_set - self.same_container_format_set
237 <= result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100238
Chris Hoge7579c1a2015-02-26 14:12:15 -0800239 @test.idempotent_id('feb32ac6-22bb-4a16-afd8-9454bb714b14')
Attila Fazekas11795b52013-02-24 15:49:08 +0100240 def test_index_max_size(self):
John Warren66207252015-07-31 15:51:02 -0400241 images_list = self.client.list_images(size_max=42)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100242 for image in images_list:
243 self.assertTrue(image['size'] <= 42)
244 result_set = set(map(lambda x: x['id'], images_list))
245 self.assertTrue(self.size42_set <= result_set)
246 self.assertFalse(self.created_set - self.size42_set <= result_set)
247
Chris Hoge7579c1a2015-02-26 14:12:15 -0800248 @test.idempotent_id('6ffc16d0-4cbf-4401-95c8-4ac63eac34d8')
Attila Fazekas11795b52013-02-24 15:49:08 +0100249 def test_index_min_size(self):
John Warren66207252015-07-31 15:51:02 -0400250 images_list = self.client.list_images(size_min=142)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100251 for image in images_list:
252 self.assertTrue(image['size'] >= 142)
253 result_set = set(map(lambda x: x['id'], images_list))
254 self.assertTrue(self.size142_set <= result_set)
255 self.assertFalse(self.size42_set <= result_set)
256
Chris Hoge7579c1a2015-02-26 14:12:15 -0800257 @test.idempotent_id('e5dc26d9-9aa2-48dd-bda5-748e1445da98')
Attila Fazekas11795b52013-02-24 15:49:08 +0100258 def test_index_status_active_detail(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000259 images_list = self.client.list_images(detail=True,
260 status='active',
261 sort_key='size',
John Warren66207252015-07-31 15:51:02 -0400262 sort_dir='desc')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100263 top_size = images_list[0]['size'] # We have non-zero sized images
264 for image in images_list:
265 size = image['size']
266 self.assertTrue(size <= top_size)
267 top_size = size
268 self.assertEqual(image['status'], 'active')
269
Chris Hoge7579c1a2015-02-26 14:12:15 -0800270 @test.idempotent_id('097af10a-bae8-4342-bff4-edf89969ed2a')
Attila Fazekas11795b52013-02-24 15:49:08 +0100271 def test_index_name(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000272 images_list = self.client.list_images(
273 detail=True,
John Warren66207252015-07-31 15:51:02 -0400274 name='New Remote Image dup')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100275 result_set = set(map(lambda x: x['id'], images_list))
276 for image in images_list:
277 self.assertEqual(image['name'], 'New Remote Image dup')
278 self.assertTrue(self.dup_set <= result_set)
279 self.assertFalse(self.created_set - self.dup_set <= result_set)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800280
281
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800282class UpdateImageMetaTest(base.BaseV1ImageTest):
283 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100284 def resource_setup(cls):
285 super(UpdateImageMetaTest, cls).resource_setup()
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900286 container_format, disk_format = get_container_and_disk_format()
287 cls.image_id = cls._create_standard_image('1', container_format,
288 disk_format, 42)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800289
290 @classmethod
291 def _create_standard_image(cls, name, container_format,
292 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000293 """Create a new standard image and return newly-registered image-id"""
294
Matthew Treinishb0c65f22015-04-23 09:09:41 -0400295 image_file = moves.cStringIO(data_utils.random_bytes(size))
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800296 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500297 image = cls.create_image(name=name,
298 container_format=container_format,
299 disk_format=disk_format,
300 is_public=False, data=image_file,
301 properties={'key1': 'value1'})
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800302 image_id = image['id']
303 return image_id
304
Chris Hoge7579c1a2015-02-26 14:12:15 -0800305 @test.idempotent_id('01752c1c-0275-4de3-9e5b-876e44541928')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800306 def test_list_image_metadata(self):
307 # All metadata key/value pairs for an image should be returned
David Kranz34f18782015-01-06 13:43:55 -0500308 resp_metadata = self.client.get_image_meta(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800309 expected = {'key1': 'value1'}
310 self.assertEqual(expected, resp_metadata['properties'])
311
Chris Hoge7579c1a2015-02-26 14:12:15 -0800312 @test.idempotent_id('d6d7649c-08ce-440d-9ea7-e3dda552f33c')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800313 def test_update_image_metadata(self):
314 # The metadata for the image should match the updated values
315 req_metadata = {'key1': 'alt1', 'key2': 'value2'}
David Kranz34f18782015-01-06 13:43:55 -0500316 metadata = self.client.get_image_meta(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800317 self.assertEqual(metadata['properties'], {'key1': 'value1'})
318 metadata['properties'].update(req_metadata)
David Kranz34f18782015-01-06 13:43:55 -0500319 metadata = self.client.update_image(
John Warren66207252015-07-31 15:51:02 -0400320 self.image_id, properties=metadata['properties'])['image']
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800321
David Kranz34f18782015-01-06 13:43:55 -0500322 resp_metadata = self.client.get_image_meta(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800323 expected = {'key1': 'alt1', 'key2': 'value2'}
324 self.assertEqual(expected, resp_metadata['properties'])