blob: 6d5559d40f4c2776c963c5ba4e8ae13491696126 [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
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030020from tempest.common import waiters
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000021from tempest import config
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090022from tempest import exceptions
ivan-zhud1bbe5d2013-12-29 18:32:46 +080023from tempest import test
Jay Pipes50677282012-01-06 15:39:20 -050024
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000025CONF = config.CONF
26
Jay Pipes50677282012-01-06 15:39:20 -050027
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090028def get_container_and_disk_format():
29 a_formats = ['ami', 'ari', 'aki']
30
31 container_format = CONF.image.container_formats[0]
32 disk_format = CONF.image.disk_formats[0]
33
34 if container_format in a_formats and container_format != disk_format:
35 msg = ("The container format and the disk format don't match. "
zhuflc35b36e2016-05-12 10:16:07 +080036 "Container format: %(container)s, Disk format: %(disk)s." %
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090037 {'container': container_format, 'disk': disk_format})
38 raise exceptions.InvalidConfiguration(message=msg)
39
40 return container_format, disk_format
41
42
Matthew Treinishce3ef922013-03-11 14:02:46 -040043class CreateRegisterImagesTest(base.BaseV1ImageTest):
44 """Here we test the registration and creation of images."""
Jay Pipes50677282012-01-06 15:39:20 -050045
Chris Hoge7579c1a2015-02-26 14:12:15 -080046 @test.idempotent_id('3027f8e6-3492-4a11-8575-c3293017af4d')
Jay Pipes50677282012-01-06 15:39:20 -050047 def test_register_then_upload(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050048 # Register, then upload an image
Matthew Treinish72ea4422013-02-07 14:42:49 -050049 properties = {'prop1': 'val1'}
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090050 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050051 body = self.create_image(name='New Name',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090052 container_format=container_format,
53 disk_format=disk_format,
David Kranz34f18782015-01-06 13:43:55 -050054 is_public=False,
55 properties=properties)
Attila Fazekase191cb12013-07-29 06:41:52 +020056 self.assertIn('id', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050057 image_id = body.get('id')
Matthew Treinish72ea4422013-02-07 14:42:49 -050058 self.assertEqual('New Name', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070059 self.assertFalse(body.get('is_public'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050060 self.assertEqual('queued', body.get('status'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050061 for key, val in properties.items():
62 self.assertEqual(val, body.get('properties')[key])
Jay Pipes50677282012-01-06 15:39:20 -050063
64 # Now try uploading an image file
Matthew Treinishb0c65f22015-04-23 09:09:41 -040065 image_file = moves.cStringIO(data_utils.random_bytes())
John Warren66207252015-07-31 15:51:02 -040066 body = self.client.update_image(image_id, data=image_file)['image']
Attila Fazekase191cb12013-07-29 06:41:52 +020067 self.assertIn('size', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050068 self.assertEqual(1024, body.get('size'))
Jay Pipes50677282012-01-06 15:39:20 -050069
Chris Hoge7579c1a2015-02-26 14:12:15 -080070 @test.idempotent_id('69da74d9-68a9-404b-9664-ff7164ccb0f5')
Jay Pipes50677282012-01-06 15:39:20 -050071 def test_register_remote_image(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050072 # Register a new remote image
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090073 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050074 body = self.create_image(name='New Remote Image',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090075 container_format=container_format,
76 disk_format=disk_format, is_public=False,
David Kranz34f18782015-01-06 13:43:55 -050077 location=CONF.image.http_image,
78 properties={'key1': 'value1',
79 'key2': 'value2'})
Attila Fazekase191cb12013-07-29 06:41:52 +020080 self.assertIn('id', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050081 self.assertEqual('New Remote Image', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070082 self.assertFalse(body.get('is_public'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050083 self.assertEqual('active', body.get('status'))
afazekas4a96bf82013-03-25 16:07:38 +010084 properties = body.get('properties')
85 self.assertEqual(properties['key1'], 'value1')
86 self.assertEqual(properties['key2'], 'value2')
Jay Pipes50677282012-01-06 15:39:20 -050087
Chris Hoge7579c1a2015-02-26 14:12:15 -080088 @test.idempotent_id('6d0e13a7-515b-460c-b91f-9f4793f09816')
Attila Fazekase72b7cd2013-03-26 18:34:21 +010089 def test_register_http_image(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090090 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050091 body = self.create_image(name='New Http Image',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090092 container_format=container_format,
93 disk_format=disk_format, is_public=False,
David Kranz34f18782015-01-06 13:43:55 -050094 copy_from=CONF.image.http_image)
Attila Fazekase191cb12013-07-29 06:41:52 +020095 self.assertIn('id', body)
Attila Fazekase72b7cd2013-03-26 18:34:21 +010096 image_id = body.get('id')
Attila Fazekase72b7cd2013-03-26 18:34:21 +010097 self.assertEqual('New Http Image', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070098 self.assertFalse(body.get('is_public'))
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030099 waiters.wait_for_image_status(self.client, image_id, 'active')
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000100 self.client.show_image(image_id)
Attila Fazekase72b7cd2013-03-26 18:34:21 +0100101
Chris Hoge7579c1a2015-02-26 14:12:15 -0800102 @test.idempotent_id('05b19d55-140c-40d0-b36b-fafd774d421b')
hi2suresh75a20302013-04-09 09:17:06 +0000103 def test_register_image_with_min_ram(self):
104 # Register an image with min ram
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900105 container_format, disk_format = get_container_and_disk_format()
hi2suresh75a20302013-04-09 09:17:06 +0000106 properties = {'prop1': 'val1'}
David Kranz34f18782015-01-06 13:43:55 -0500107 body = self.create_image(name='New_image_with_min_ram',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900108 container_format=container_format,
109 disk_format=disk_format,
David Kranz34f18782015-01-06 13:43:55 -0500110 is_public=False,
111 min_ram=40,
112 properties=properties)
Attila Fazekase191cb12013-07-29 06:41:52 +0200113 self.assertIn('id', body)
hi2suresh75a20302013-04-09 09:17:06 +0000114 self.assertEqual('New_image_with_min_ram', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -0700115 self.assertFalse(body.get('is_public'))
hi2suresh75a20302013-04-09 09:17:06 +0000116 self.assertEqual('queued', body.get('status'))
117 self.assertEqual(40, body.get('min_ram'))
118 for key, val in properties.items():
119 self.assertEqual(val, body.get('properties')[key])
David Kranz9c3b3b62014-06-19 16:05:53 -0400120 self.client.delete_image(body['id'])
hi2suresh75a20302013-04-09 09:17:06 +0000121
Jay Pipes50677282012-01-06 15:39:20 -0500122
Matthew Treinishce3ef922013-03-11 14:02:46 -0400123class ListImagesTest(base.BaseV1ImageTest):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000124 """Here we test the listing of image information"""
Jay Pipes50677282012-01-06 15:39:20 -0500125
126 @classmethod
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900127 def skip_checks(cls):
128 super(ListImagesTest, cls).skip_checks()
129 if (len(CONF.image.container_formats) < 2
130 or len(CONF.image.disk_formats) < 2):
131 skip_msg = ("%s skipped as multiple container formats "
132 "or disk formats are not available." % cls.__name__)
133 raise cls.skipException(skip_msg)
134
135 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100136 def resource_setup(cls):
137 super(ListImagesTest, cls).resource_setup()
Jay Pipes50677282012-01-06 15:39:20 -0500138 # We add a few images here to test the listing functionality of
139 # the images API
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900140 a_formats = ['ami', 'ari', 'aki']
141
142 (cls.container_format,
143 cls.container_format_alt) = CONF.image.container_formats[:2]
144 cls.disk_format, cls.disk_format_alt = CONF.image.disk_formats[:2]
145 if cls.container_format in a_formats:
146 cls.disk_format = cls.container_format
147 if cls.container_format_alt in a_formats:
148 cls.disk_format_alt = cls.container_format_alt
149
150 img1 = cls._create_remote_image('one', cls.container_format,
151 cls.disk_format)
152 img2 = cls._create_remote_image('two', cls.container_format_alt,
153 cls.disk_format_alt)
154 img3 = cls._create_remote_image('dup', cls.container_format,
155 cls.disk_format)
156 img4 = cls._create_remote_image('dup', cls.container_format,
157 cls.disk_format)
158 img5 = cls._create_standard_image('1', cls.container_format_alt,
159 cls.disk_format_alt, 42)
160 img6 = cls._create_standard_image('2', cls.container_format_alt,
161 cls.disk_format_alt, 142)
162 img7 = cls._create_standard_image('33', cls.container_format,
163 cls.disk_format, 142)
164 img8 = cls._create_standard_image('33', cls.container_format,
165 cls.disk_format, 142)
Attila Fazekas11795b52013-02-24 15:49:08 +0100166 cls.created_set = set(cls.created_images)
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900167 # same container format
168 cls.same_container_format_set = set((img1, img3, img4, img7, img8))
169 # same disk format
170 cls.same_disk_format_set = set((img2, img5, img6))
171
Attila Fazekas11795b52013-02-24 15:49:08 +0100172 # 1x with size 42
173 cls.size42_set = set((img5,))
174 # 3x with size 142
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800175 cls.size142_set = set((img6, img7, img8,))
Attila Fazekas11795b52013-02-24 15:49:08 +0100176 # dup named
177 cls.dup_set = set((img3, img4))
Jay Pipes50677282012-01-06 15:39:20 -0500178
179 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100180 def _create_remote_image(cls, name, container_format, disk_format):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000181 """Create a new remote image and return newly-registered image-id"""
182
Attila Fazekas11795b52013-02-24 15:49:08 +0100183 name = 'New Remote Image %s' % name
Matthew Treinishe81ae692014-06-19 17:41:31 -0400184 location = CONF.image.http_image
David Kranz34f18782015-01-06 13:43:55 -0500185 image = cls.create_image(name=name,
186 container_format=container_format,
187 disk_format=disk_format,
188 is_public=False,
189 location=location)
Attila Fazekas11795b52013-02-24 15:49:08 +0100190 image_id = image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500191 return image_id
192
193 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100194 def _create_standard_image(cls, name, container_format,
195 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000196 """Create a new standard image and return newly-registered image-id
197
198 Note that the size of the new image is a random number between
Jay Pipes50677282012-01-06 15:39:20 -0500199 1024 and 4096
200 """
Matthew Treinishb0c65f22015-04-23 09:09:41 -0400201 image_file = moves.cStringIO(data_utils.random_bytes(size))
Attila Fazekas11795b52013-02-24 15:49:08 +0100202 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500203 image = cls.create_image(name=name,
204 container_format=container_format,
205 disk_format=disk_format,
206 is_public=False, data=image_file)
Attila Fazekas11795b52013-02-24 15:49:08 +0100207 image_id = image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500208 return image_id
209
Chris Hoge7579c1a2015-02-26 14:12:15 -0800210 @test.idempotent_id('246178ab-3b33-4212-9a4b-a7fe8261794d')
Jay Pipes50677282012-01-06 15:39:20 -0500211 def test_index_no_params(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -0500212 # Simple test to see all fixture images returned
John Warren66207252015-07-31 15:51:02 -0400213 images_list = self.client.list_images()['images']
Matthew Treinish72ea4422013-02-07 14:42:49 -0500214 image_list = map(lambda x: x['id'], images_list)
Attila Fazekas11795b52013-02-24 15:49:08 +0100215 for image_id in self.created_images:
Attila Fazekase191cb12013-07-29 06:41:52 +0200216 self.assertIn(image_id, image_list)
Attila Fazekas11795b52013-02-24 15:49:08 +0100217
Chris Hoge7579c1a2015-02-26 14:12:15 -0800218 @test.idempotent_id('f1755589-63d6-4468-b098-589820eb4031')
Attila Fazekas11795b52013-02-24 15:49:08 +0100219 def test_index_disk_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900220 images_list = self.client.list_images(
221 disk_format=self.disk_format_alt)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100222 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900223 self.assertEqual(image['disk_format'], self.disk_format_alt)
Attila Fazekas11795b52013-02-24 15:49:08 +0100224 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900225 self.assertTrue(self.same_disk_format_set <= result_set)
226 self.assertFalse(self.created_set - self.same_disk_format_set
227 <= result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100228
Chris Hoge7579c1a2015-02-26 14:12:15 -0800229 @test.idempotent_id('2143655d-96d9-4bec-9188-8674206b4b3b')
Attila Fazekas11795b52013-02-24 15:49:08 +0100230 def test_index_container_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900231 images_list = self.client.list_images(
232 container_format=self.container_format)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100233 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900234 self.assertEqual(image['container_format'], self.container_format)
Attila Fazekas11795b52013-02-24 15:49:08 +0100235 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900236 self.assertTrue(self.same_container_format_set <= result_set)
237 self.assertFalse(self.created_set - self.same_container_format_set
238 <= result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100239
Chris Hoge7579c1a2015-02-26 14:12:15 -0800240 @test.idempotent_id('feb32ac6-22bb-4a16-afd8-9454bb714b14')
Attila Fazekas11795b52013-02-24 15:49:08 +0100241 def test_index_max_size(self):
John Warren66207252015-07-31 15:51:02 -0400242 images_list = self.client.list_images(size_max=42)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100243 for image in images_list:
244 self.assertTrue(image['size'] <= 42)
245 result_set = set(map(lambda x: x['id'], images_list))
246 self.assertTrue(self.size42_set <= result_set)
247 self.assertFalse(self.created_set - self.size42_set <= result_set)
248
Chris Hoge7579c1a2015-02-26 14:12:15 -0800249 @test.idempotent_id('6ffc16d0-4cbf-4401-95c8-4ac63eac34d8')
Attila Fazekas11795b52013-02-24 15:49:08 +0100250 def test_index_min_size(self):
John Warren66207252015-07-31 15:51:02 -0400251 images_list = self.client.list_images(size_min=142)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100252 for image in images_list:
253 self.assertTrue(image['size'] >= 142)
254 result_set = set(map(lambda x: x['id'], images_list))
255 self.assertTrue(self.size142_set <= result_set)
256 self.assertFalse(self.size42_set <= result_set)
257
Chris Hoge7579c1a2015-02-26 14:12:15 -0800258 @test.idempotent_id('e5dc26d9-9aa2-48dd-bda5-748e1445da98')
Attila Fazekas11795b52013-02-24 15:49:08 +0100259 def test_index_status_active_detail(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000260 images_list = self.client.list_images(detail=True,
261 status='active',
262 sort_key='size',
John Warren66207252015-07-31 15:51:02 -0400263 sort_dir='desc')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100264 top_size = images_list[0]['size'] # We have non-zero sized images
265 for image in images_list:
266 size = image['size']
267 self.assertTrue(size <= top_size)
268 top_size = size
269 self.assertEqual(image['status'], 'active')
270
Chris Hoge7579c1a2015-02-26 14:12:15 -0800271 @test.idempotent_id('097af10a-bae8-4342-bff4-edf89969ed2a')
Attila Fazekas11795b52013-02-24 15:49:08 +0100272 def test_index_name(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000273 images_list = self.client.list_images(
274 detail=True,
John Warren66207252015-07-31 15:51:02 -0400275 name='New Remote Image dup')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100276 result_set = set(map(lambda x: x['id'], images_list))
277 for image in images_list:
278 self.assertEqual(image['name'], 'New Remote Image dup')
279 self.assertTrue(self.dup_set <= result_set)
280 self.assertFalse(self.created_set - self.dup_set <= result_set)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800281
282
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800283class UpdateImageMetaTest(base.BaseV1ImageTest):
284 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100285 def resource_setup(cls):
286 super(UpdateImageMetaTest, cls).resource_setup()
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900287 container_format, disk_format = get_container_and_disk_format()
288 cls.image_id = cls._create_standard_image('1', container_format,
289 disk_format, 42)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800290
291 @classmethod
292 def _create_standard_image(cls, name, container_format,
293 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000294 """Create a new standard image and return newly-registered image-id"""
295
Matthew Treinishb0c65f22015-04-23 09:09:41 -0400296 image_file = moves.cStringIO(data_utils.random_bytes(size))
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800297 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500298 image = cls.create_image(name=name,
299 container_format=container_format,
300 disk_format=disk_format,
301 is_public=False, data=image_file,
302 properties={'key1': 'value1'})
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800303 image_id = image['id']
304 return image_id
305
Chris Hoge7579c1a2015-02-26 14:12:15 -0800306 @test.idempotent_id('01752c1c-0275-4de3-9e5b-876e44541928')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800307 def test_list_image_metadata(self):
308 # All metadata key/value pairs for an image should be returned
Yaroslav Lobankov9d28a0f2016-04-19 15:05:57 +0300309 resp_metadata = self.client.check_image(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800310 expected = {'key1': 'value1'}
311 self.assertEqual(expected, resp_metadata['properties'])
312
Chris Hoge7579c1a2015-02-26 14:12:15 -0800313 @test.idempotent_id('d6d7649c-08ce-440d-9ea7-e3dda552f33c')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800314 def test_update_image_metadata(self):
315 # The metadata for the image should match the updated values
316 req_metadata = {'key1': 'alt1', 'key2': 'value2'}
Yaroslav Lobankov9d28a0f2016-04-19 15:05:57 +0300317 metadata = self.client.check_image(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800318 self.assertEqual(metadata['properties'], {'key1': 'value1'})
319 metadata['properties'].update(req_metadata)
David Kranz34f18782015-01-06 13:43:55 -0500320 metadata = self.client.update_image(
John Warren66207252015-07-31 15:51:02 -0400321 self.image_id, properties=metadata['properties'])['image']
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800322
Yaroslav Lobankov9d28a0f2016-04-19 15:05:57 +0300323 resp_metadata = self.client.check_image(self.image_id)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800324 expected = {'key1': 'alt1', 'key2': 'value2'}
325 self.assertEqual(expected, resp_metadata['properties'])