blob: 28299a47ef008e9fb6c6f8e605f219049274e57f [file] [log] [blame]
ZhiQiang Fan39f97222013-09-20 04:49:44 +08001# Copyright 2013 OpenStack Foundation
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +05302# Copyright 2013 IBM Corp
Matthew Treinisha62347f2013-03-01 16:37:30 -05003# All Rights Reserved.
Matthew Treinisha62347f2013-03-01 16:37:30 -05004#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
Matthew Treinisha62347f2013-03-01 16:37:30 -050017import random
18
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053019import six
Matthew Treinish01472ff2015-02-20 17:26:52 -050020
Takashi NATSUME12a48512015-08-10 18:33:16 +090021from oslo_log import log as logging
Sean Dague1937d092013-05-17 16:36:38 -040022from tempest.api.image import base
PranaliD491d63e2020-08-18 13:29:21 +000023from tempest.common import waiters
Takashi NATSUME12a48512015-08-10 18:33:16 +090024from tempest import config
Ken'ichi Ohmichicc01c3e2017-03-10 10:48:14 -080025from tempest.lib.common.utils import data_utils
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -080026from tempest.lib import decorators
lkuchlan32b53c32017-04-20 16:51:08 +030027from tempest.lib import exceptions as lib_exc
Matthew Treinisha62347f2013-03-01 16:37:30 -050028
Takashi NATSUME12a48512015-08-10 18:33:16 +090029CONF = config.CONF
30LOG = logging.getLogger(__name__)
31
Matthew Treinisha62347f2013-03-01 16:37:30 -050032
Abhishek Kekane7cff1302020-07-16 10:30:13 +000033class ImportImagesTest(base.BaseV2ImageTest):
34 """Here we test the import operations for image"""
35
36 @classmethod
37 def skip_checks(cls):
38 super(ImportImagesTest, cls).skip_checks()
39 if not CONF.image_feature_enabled.import_image:
40 skip_msg = (
41 "%s skipped as image import is not available" % cls.__name__)
42 raise cls.skipException(skip_msg)
43
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050044 @classmethod
45 def resource_setup(cls):
46 super(ImportImagesTest, cls).resource_setup()
47 cls.available_import_methods = cls.client.info_import()[
48 'import-methods']['value']
49 if not cls.available_import_methods:
50 raise cls.skipException('Server does not support '
51 'any import method')
Abhishek Kekane7cff1302020-07-16 10:30:13 +000052
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050053 def _create_image(self):
Abhishek Kekane7cff1302020-07-16 10:30:13 +000054 # Create image
55 uuid = '00000000-1111-2222-3333-444455556666'
56 image_name = data_utils.rand_name('image')
57 container_format = CONF.image.container_formats[0]
58 disk_format = CONF.image.disk_formats[0]
59 image = self.create_image(name=image_name,
60 container_format=container_format,
61 disk_format=disk_format,
62 visibility='private',
63 ramdisk_id=uuid)
64 self.assertIn('name', image)
65 self.assertEqual(image_name, image['name'])
66 self.assertIn('visibility', image)
67 self.assertEqual('private', image['visibility'])
68 self.assertIn('status', image)
69 self.assertEqual('queued', image['status'])
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050070 return image
Abhishek Kekane7cff1302020-07-16 10:30:13 +000071
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050072 @decorators.idempotent_id('32ca0c20-e16f-44ac-8590-07869c9b4cc2')
73 def test_image_glance_direct_import(self):
74 """Test 'glance-direct' import functionalities
75
76 Create image, stage image data, import image and verify
77 that import succeeded.
78 """
79 if 'glance-direct' not in self.available_import_methods:
80 raise self.skipException('Server does not support '
81 'glance-direct import method')
82 image = self._create_image()
Abhishek Kekane7cff1302020-07-16 10:30:13 +000083 # Stage image data
84 file_content = data_utils.random_bytes()
85 image_file = six.BytesIO(file_content)
86 self.client.stage_image_file(image['id'], image_file)
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050087 # Check image status is 'uploading'
88 body = self.client.show_image(image['id'])
89 self.assertEqual(image['id'], body['id'])
90 self.assertEqual('uploading', body['status'])
91 # import image from staging to backend
92 self.client.image_import(image['id'], method='glance-direct')
93 self.client.wait_for_resource_activation(image['id'])
Abhishek Kekane7cff1302020-07-16 10:30:13 +000094
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -050095 @decorators.idempotent_id('f6feb7a4-b04f-4706-a011-206129f83e62')
96 def test_image_web_download_import(self):
97 """Test 'web-download' import functionalities
98
99 Create image, import image and verify that import
100 succeeded.
101 """
102 if 'web-download' not in self.available_import_methods:
103 raise self.skipException('Server does not support '
104 'web-download import method')
105 image = self._create_image()
Abhishek Kekane7cff1302020-07-16 10:30:13 +0000106 # Now try to get image details
107 body = self.client.show_image(image['id'])
108 self.assertEqual(image['id'], body['id'])
Ghanshyam Mann1425ecd2020-07-22 21:01:26 -0500109 self.assertEqual('queued', body['status'])
110 # import image from web to backend
111 image_uri = CONF.image.http_image
112 self.client.image_import(image['id'], method='web-download',
113 image_uri=image_uri)
Abhishek Kekane7cff1302020-07-16 10:30:13 +0000114 self.client.wait_for_resource_activation(image['id'])
115
116
PranaliD491d63e2020-08-18 13:29:21 +0000117class MultiStoresImportImagesTest(base.BaseV2ImageTest):
118 """Test importing image in multiple stores"""
119 @classmethod
120 def skip_checks(cls):
121 super(MultiStoresImportImagesTest, cls).skip_checks()
122 if not CONF.image_feature_enabled.import_image:
123 skip_msg = (
124 "%s skipped as image import is not available" % cls.__name__)
125 raise cls.skipException(skip_msg)
126
127 @classmethod
128 def resource_setup(cls):
129 super(MultiStoresImportImagesTest, cls).resource_setup()
130 cls.available_import_methods = cls.client.info_import()[
131 'import-methods']['value']
132 if not cls.available_import_methods:
133 raise cls.skipException('Server does not support '
134 'any import method')
135
136 # NOTE(pdeore): Skip if glance-direct import method and mutlistore
137 # are not enabled/configured, or only one store is configured in
138 # multiple stores setup.
139 cls.available_stores = cls.get_available_stores()
140 if ('glance-direct' not in cls.available_import_methods or
141 not len(cls.available_stores) > 1):
142 raise cls.skipException(
143 'Either glance-direct import method not present in %s or '
144 'None or only one store is '
145 'configured %s' % (cls.available_import_methods,
146 cls.available_stores))
147
148 def _create_and_stage_image(self, all_stores=False):
149 """Create Image & stage image file for glance-direct import method."""
150 image_name = data_utils.rand_name('test-image')
151 container_format = CONF.image.container_formats[0]
152 disk_format = CONF.image.disk_formats[0]
153 image = self.create_image(name=image_name,
154 container_format=container_format,
155 disk_format=disk_format,
156 visibility='private')
157 self.assertEqual('queued', image['status'])
158
159 self.client.stage_image_file(
160 image['id'],
161 six.BytesIO(data_utils.random_bytes(10485760)))
162 # Check image status is 'uploading'
163 body = self.client.show_image(image['id'])
164 self.assertEqual(image['id'], body['id'])
165 self.assertEqual('uploading', body['status'])
166
167 if all_stores:
168 stores_list = ','.join([store['id']
169 for store in self.available_stores])
170 else:
171 stores = [store['id'] for store in self.available_stores]
172 stores_list = stores[::len(stores) - 1]
173
174 return body, stores_list
175
176 @decorators.idempotent_id('bf04ff00-3182-47cb-833a-f1c6767b47fd')
177 def test_glance_direct_import_image_to_all_stores(self):
178 """Test image is imported in all available stores
179
180 Create image, import image to all available stores using glance-direct
181 import method and verify that import succeeded.
182 """
183 image, stores = self._create_and_stage_image(all_stores=True)
184
185 self.client.image_import(
186 image['id'], method='glance-direct', all_stores=True)
187
188 waiters.wait_for_image_imported_to_stores(self.client,
189 image['id'], stores)
190
191 @decorators.idempotent_id('82fb131a-dd2b-11ea-aec7-340286b6c574')
192 def test_glance_direct_import_image_to_specific_stores(self):
193 """Test image is imported in all available stores
194
195 Create image, import image to specified store(s) using glance-direct
196 import method and verify that import succeeded.
197 """
198 image, stores = self._create_and_stage_image()
199 self.client.image_import(image['id'], method='glance-direct',
200 stores=stores)
201
202 waiters.wait_for_image_imported_to_stores(self.client, image['id'],
203 (','.join(stores)))
204
205
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530206class BasicOperationsImagesTest(base.BaseV2ImageTest):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000207 """Here we test the basic operations of images"""
Matthew Treinisha62347f2013-03-01 16:37:30 -0500208
Jordan Pittier3b46d272017-04-12 16:17:28 +0200209 @decorators.attr(type='smoke')
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800210 @decorators.idempotent_id('139b765e-7f3d-4b3d-8b37-3ca3876ee318')
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530211 def test_register_upload_get_image_file(self):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000212 """Here we test these functionalities
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530213
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000214 Register image, upload the image file, get image and get image
215 file api's
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530216 """
217
Sean Daguec6ec4762014-05-29 08:54:21 -0400218 uuid = '00000000-1111-2222-3333-444455556666'
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530219 image_name = data_utils.rand_name('image')
Takashi NATSUME12a48512015-08-10 18:33:16 +0900220 container_format = CONF.image.container_formats[0]
221 disk_format = CONF.image.disk_formats[0]
lkuchlanb3348792016-09-29 10:42:21 +0300222 image = self.create_image(name=image_name,
223 container_format=container_format,
224 disk_format=disk_format,
225 visibility='private',
226 ramdisk_id=uuid)
lkuchlanb3348792016-09-29 10:42:21 +0300227 self.assertIn('name', image)
228 self.assertEqual(image_name, image['name'])
229 self.assertIn('visibility', image)
230 self.assertEqual('private', image['visibility'])
231 self.assertIn('status', image)
232 self.assertEqual('queued', image['status'])
Matthew Treinisha62347f2013-03-01 16:37:30 -0500233
wangxiyuan99e4dcf2019-09-17 09:51:55 +0800234 # NOTE: This Glance API returns different status codes for image
235 # condition. In this empty data case, Glance should return 204,
236 # so here should check the status code.
237 image_file = self.client.show_image_file(image['id'])
238 self.assertEqual(0, len(image_file.data))
239 self.assertEqual(204, image_file.response.status)
240
Matthew Treinisha62347f2013-03-01 16:37:30 -0500241 # Now try uploading an image file
Mark Washenberger5c3b6fe2014-07-29 13:40:34 -0700242 file_content = data_utils.random_bytes()
Sirushti Murugesan12dc9732016-07-13 22:49:17 +0530243 image_file = six.BytesIO(file_content)
lkuchlanb3348792016-09-29 10:42:21 +0300244 self.client.store_image_file(image['id'], image_file)
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530245
246 # Now try to get image details
lkuchlanb3348792016-09-29 10:42:21 +0300247 body = self.client.show_image(image['id'])
248 self.assertEqual(image['id'], body['id'])
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530249 self.assertEqual(image_name, body['name'])
Sean Daguec6ec4762014-05-29 08:54:21 -0400250 self.assertEqual(uuid, body['ramdisk_id'])
Attila Fazekase191cb12013-07-29 06:41:52 +0200251 self.assertIn('size', body)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500252 self.assertEqual(1024, body.get('size'))
253
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530254 # Now try get image file
Ken'ichi Ohmichi3b79f172018-03-20 11:31:44 -0700255 # NOTE: This Glance API returns different status codes for image
256 # condition. In this non-empty data case, Glance should return 200,
257 # so here should check the status code.
lkuchlanb3348792016-09-29 10:42:21 +0300258 body = self.client.show_image_file(image['id'])
David Kranzd7e97b42015-02-16 09:37:31 -0500259 self.assertEqual(file_content, body.data)
Ken'ichi Ohmichi3b79f172018-03-20 11:31:44 -0700260 self.assertEqual(200, body.response.status)
Hoisaleshwara Madan V Se50a6f12013-10-23 18:01:01 +0530261
Jordan Pittier3b46d272017-04-12 16:17:28 +0200262 @decorators.attr(type='smoke')
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800263 @decorators.idempotent_id('f848bb94-1c6e-45a4-8726-39e3a5b23535')
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530264 def test_delete_image(self):
zhufle68f4352020-04-21 13:44:55 +0800265 """Test deleting an image by image_id"""
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530266 # Create image
267 image_name = data_utils.rand_name('image')
Takashi NATSUME12a48512015-08-10 18:33:16 +0900268 container_format = CONF.image.container_formats[0]
269 disk_format = CONF.image.disk_formats[0]
Benny Kopilov900fceb2016-11-09 09:45:40 +0200270 image = self.create_image(name=image_name,
271 container_format=container_format,
272 disk_format=disk_format,
273 visibility='private')
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530274 # Delete Image
lkuchlanb3348792016-09-29 10:42:21 +0300275 self.client.delete_image(image['id'])
276 self.client.wait_for_resource_deletion(image['id'])
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530277
278 # Verifying deletion
John Warrenf3b3e952015-08-17 19:28:12 +0000279 images = self.client.list_images()['images']
Sunil G29856a32014-07-17 23:17:58 +0530280 images_id = [item['id'] for item in images]
lkuchlanb3348792016-09-29 10:42:21 +0300281 self.assertNotIn(image['id'], images_id)
Hoisaleshwara Madan V S7cba1082013-11-26 12:43:04 +0530282
Jordan Pittier3b46d272017-04-12 16:17:28 +0200283 @decorators.attr(type='smoke')
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800284 @decorators.idempotent_id('f66891a7-a35c-41a8-b590-a065c2a1caa6')
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400285 def test_update_image(self):
zhufle68f4352020-04-21 13:44:55 +0800286 """Test updating an image by image_id"""
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400287 # Create image
288 image_name = data_utils.rand_name('image')
Takashi NATSUME12a48512015-08-10 18:33:16 +0900289 container_format = CONF.image.container_formats[0]
290 disk_format = CONF.image.disk_formats[0]
Benny Kopilov900fceb2016-11-09 09:45:40 +0200291 image = self.create_image(name=image_name,
292 container_format=container_format,
293 disk_format=disk_format,
294 visibility='private')
lkuchlanb3348792016-09-29 10:42:21 +0300295 self.assertEqual('queued', image['status'])
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400296
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400297 # Update Image
298 new_image_name = data_utils.rand_name('new-image')
zhufl311104e2017-08-17 15:13:18 +0800299 self.client.update_image(image['id'], [
Aaron Rosenc7720622014-05-20 10:38:10 -0700300 dict(replace='/name', value=new_image_name)])
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400301
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400302 # Verifying updating
303
lkuchlanb3348792016-09-29 10:42:21 +0300304 body = self.client.show_image(image['id'])
305 self.assertEqual(image['id'], body['id'])
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400306 self.assertEqual(new_image_name, body['name'])
Sergey Nikitinc6b2ee82014-02-03 17:13:50 +0400307
lkuchlan32b53c32017-04-20 16:51:08 +0300308 @decorators.idempotent_id('951ebe01-969f-4ea9-9898-8a3f1f442ab0')
309 def test_deactivate_reactivate_image(self):
zhufle68f4352020-04-21 13:44:55 +0800310 """Test deactivating and reactivating an image"""
lkuchlan32b53c32017-04-20 16:51:08 +0300311 # Create image
312 image_name = data_utils.rand_name('image')
313 image = self.create_image(name=image_name,
314 container_format='bare',
315 disk_format='raw',
316 visibility='private')
317
318 # Upload an image file
319 content = data_utils.random_bytes()
320 image_file = six.BytesIO(content)
321 self.client.store_image_file(image['id'], image_file)
322
323 # Deactivate image
324 self.client.deactivate_image(image['id'])
325 body = self.client.show_image(image['id'])
326 self.assertEqual("deactivated", body['status'])
327
328 # User unable to download deactivated image
329 self.assertRaises(lib_exc.Forbidden, self.client.show_image_file,
330 image['id'])
331
332 # Reactivate image
333 self.client.reactivate_image(image['id'])
334 body = self.client.show_image(image['id'])
335 self.assertEqual("active", body['status'])
336
337 # User able to download image after reactivation
338 body = self.client.show_image_file(image['id'])
339 self.assertEqual(content, body.data)
340
Matthew Treinisha62347f2013-03-01 16:37:30 -0500341
zhufl6e042bc2017-01-25 10:33:40 +0800342class ListUserImagesTest(base.BaseV2ImageTest):
343 """Here we test the listing of image information"""
Matthew Treinisha62347f2013-03-01 16:37:30 -0500344
345 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100346 def resource_setup(cls):
zhufl6e042bc2017-01-25 10:33:40 +0800347 super(ListUserImagesTest, cls).resource_setup()
Matthew Treinisha62347f2013-03-01 16:37:30 -0500348 # We add a few images here to test the listing functionality of
349 # the images API
Takashi NATSUME12a48512015-08-10 18:33:16 +0900350 container_fmts = CONF.image.container_formats
351 disk_fmts = CONF.image.disk_formats
352 all_pairs = [(container_fmt, disk_fmt)
353 for container_fmt in container_fmts
354 for disk_fmt in disk_fmts]
355
356 for (container_fmt, disk_fmt) in all_pairs[:6]:
Sergey Vilgelm36fdd202018-11-20 16:10:47 -0600357 LOG.debug("Creating an image "
Takashi NATSUME12a48512015-08-10 18:33:16 +0900358 "(Container format: %s, Disk format: %s).",
359 container_fmt, disk_fmt)
360 cls._create_standard_image(container_fmt, disk_fmt)
Matthew Treinisha62347f2013-03-01 16:37:30 -0500361
362 @classmethod
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700363 def _create_standard_image(cls, container_format, disk_format):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000364 """Create a new standard image and return the newly-registered image-id
365
366 Note that the size of the new image is a random number between
Matthew Treinisha62347f2013-03-01 16:37:30 -0500367 1024 and 4096
368 """
Mark Washenberger5c3b6fe2014-07-29 13:40:34 -0700369 size = random.randint(1024, 4096)
Sirushti Murugesan12dc9732016-07-13 22:49:17 +0530370 image_file = six.BytesIO(data_utils.random_bytes(size))
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700371 tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
zhufl08e42762016-10-18 16:07:56 +0800372 image = cls.create_image(container_format=container_format,
lkuchlanb3348792016-09-29 10:42:21 +0300373 disk_format=disk_format,
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700374 visibility='private',
375 tags=tags)
lkuchlanb3348792016-09-29 10:42:21 +0300376 cls.client.store_image_file(image['id'], data=image_file)
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700377 # Keep the data of one test image so it can be used to filter lists
378 cls.test_data = image
Matthew Treinisha62347f2013-03-01 16:37:30 -0500379
lkuchlanb3348792016-09-29 10:42:21 +0300380 return image['id']
Matthew Treinisha62347f2013-03-01 16:37:30 -0500381
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700382 def _list_by_param_value_and_assert(self, params):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000383 """Perform list action with given params and validates result."""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700384 # Retrieve the list of images that meet the filter
John Warrenf3b3e952015-08-17 19:28:12 +0000385 images_list = self.client.list_images(params=params)['images']
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700386 # Validating params of fetched images
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700387 msg = 'No images were found that met the filter criteria.'
388 self.assertNotEmpty(images_list, msg)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700389 for image in images_list:
390 for key in params:
391 msg = "Failed to list images by %s" % key
392 self.assertEqual(params[key], image[key], msg)
393
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700394 def _list_sorted_by_image_size_and_assert(self, params, desc=False):
395 """Validate an image list that has been sorted by size
396
397 Perform list action with given params and validates the results are
398 sorted by image size in either ascending or descending order.
399 """
400 # Retrieve the list of images that meet the filter
401 images_list = self.client.list_images(params=params)['images']
402 # Validate that the list was fetched sorted accordingly
403 msg = 'No images were found that met the filter criteria.'
404 self.assertNotEmpty(images_list, msg)
405 sorted_list = [image['size'] for image in images_list]
406 msg = 'The list of images was not sorted correctly.'
407 self.assertEqual(sorted(sorted_list, reverse=desc), sorted_list, msg)
408
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800409 @decorators.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
Flavio Percoco7e26be12015-09-15 22:33:19 +0200410 def test_list_no_params(self):
zhufle68f4352020-04-21 13:44:55 +0800411 """Simple test to see all fixture images returned"""
John Warrenf3b3e952015-08-17 19:28:12 +0000412 images_list = self.client.list_images()['images']
Sirushti Murugesan935f2cc2016-07-12 19:48:24 +0530413 image_list = [image['id'] for image in images_list]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700414
Matthew Treinisha62347f2013-03-01 16:37:30 -0500415 for image in self.created_images:
Attila Fazekase191cb12013-07-29 06:41:52 +0200416 self.assertIn(image, image_list)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700417
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800418 @decorators.idempotent_id('9959ca1d-1aa7-4b7a-a1ea-0fff0499b37e')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700419 def test_list_images_param_container_format(self):
zhufle68f4352020-04-21 13:44:55 +0800420 """Test to get all images with a specific container_format"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700421 params = {"container_format": self.test_data['container_format']}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700422 self._list_by_param_value_and_assert(params)
423
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800424 @decorators.idempotent_id('4a4735a7-f22f-49b6-b0d9-66e1ef7453eb')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700425 def test_list_images_param_disk_format(self):
zhufle68f4352020-04-21 13:44:55 +0800426 """Test to get all images with disk_format = raw"""
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700427 params = {"disk_format": "raw"}
428 self._list_by_param_value_and_assert(params)
429
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800430 @decorators.idempotent_id('7a95bb92-d99e-4b12-9718-7bc6ab73e6d2')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700431 def test_list_images_param_visibility(self):
zhufle68f4352020-04-21 13:44:55 +0800432 """Test to get all images with visibility = private"""
Aaron Rosenc7720622014-05-20 10:38:10 -0700433 params = {"visibility": "private"}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700434 self._list_by_param_value_and_assert(params)
435
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800436 @decorators.idempotent_id('cf1b9a48-8340-480e-af7b-fe7e17690876')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700437 def test_list_images_param_size(self):
zhufle68f4352020-04-21 13:44:55 +0800438 """Test to get all images by size"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900439 image_id = self.created_images[0]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700440 # Get image metadata
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000441 image = self.client.show_image(image_id)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700442
443 params = {"size": image['size']}
444 self._list_by_param_value_and_assert(params)
445
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800446 @decorators.idempotent_id('4ad8c157-971a-4ba8-aa84-ed61154b1e7f')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700447 def test_list_images_param_min_max_size(self):
zhufle68f4352020-04-21 13:44:55 +0800448 """Test to get all images with min size and max size"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900449 image_id = self.created_images[0]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700450 # Get image metadata
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000451 image = self.client.show_image(image_id)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700452
453 size = image['size']
454 params = {"size_min": size - 500, "size_max": size + 500}
John Warrenf3b3e952015-08-17 19:28:12 +0000455 images_list = self.client.list_images(params=params)['images']
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700456 image_size_list = map(lambda x: x['size'], images_list)
457
458 for image_size in image_size_list:
Béla Vancsics64862f72016-11-08 09:12:31 +0100459 self.assertGreaterEqual(image_size, params['size_min'],
460 "Failed to get images by size_min")
461 self.assertLessEqual(image_size, params['size_max'],
462 "Failed to get images by size_max")
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700463
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800464 @decorators.idempotent_id('7fc9e369-0f58-4d05-9aa5-0969e2d59d15')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700465 def test_list_images_param_status(self):
zhufle68f4352020-04-21 13:44:55 +0800466 """Test to get all active images"""
Anju Tiwarica2249d2014-01-23 17:33:02 +0530467 params = {"status": "active"}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700468 self._list_by_param_value_and_assert(params)
469
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800470 @decorators.idempotent_id('e914a891-3cc8-4b40-ad32-e0a39ffbddbb')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700471 def test_list_images_param_limit(self):
zhufle68f4352020-04-21 13:44:55 +0800472 """Test to get images by limit"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900473 params = {"limit": 1}
John Warrenf3b3e952015-08-17 19:28:12 +0000474 images_list = self.client.list_images(params=params)['images']
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700475
476 self.assertEqual(len(images_list), params['limit'],
477 "Failed to get images by limit")
raiesmh08a1ce3542014-03-04 11:58:29 +0530478
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800479 @decorators.idempotent_id('e9a44b91-31c8-4b40-a332-e0a39ffb4dbb')
Li Wei14bf2412016-09-25 15:56:23 +0800480 def test_list_image_param_owner(self):
zhufle68f4352020-04-21 13:44:55 +0800481 """Test to get images by owner"""
Li Wei14bf2412016-09-25 15:56:23 +0800482 image_id = self.created_images[0]
483 # Get image metadata
484 image = self.client.show_image(image_id)
485
486 params = {"owner": image['owner']}
487 self._list_by_param_value_and_assert(params)
488
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800489 @decorators.idempotent_id('55c8f5f5-bfed-409d-a6d5-4caeda985d7b')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700490 def test_list_images_param_name(self):
zhufle68f4352020-04-21 13:44:55 +0800491 """Test to get images by name"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700492 params = {'name': self.test_data['name']}
493 self._list_by_param_value_and_assert(params)
494
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800495 @decorators.idempotent_id('aa8ac4df-cff9-418b-8d0f-dd9c67b072c9')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700496 def test_list_images_param_tag(self):
zhufle68f4352020-04-21 13:44:55 +0800497 """Test to get images matching a tag"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700498 params = {'tag': self.test_data['tags'][0]}
499 images_list = self.client.list_images(params=params)['images']
500 # Validating properties of fetched images
501 self.assertNotEmpty(images_list)
502 for image in images_list:
503 msg = ("The image {image_name} does not have the expected tag "
504 "{expected_tag} among its tags: {observerd_tags}."
505 .format(image_name=image['name'],
506 expected_tag=self.test_data['tags'][0],
507 observerd_tags=image['tags']))
508 self.assertIn(self.test_data['tags'][0], image['tags'], msg)
509
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800510 @decorators.idempotent_id('eeadce49-04e0-43b7-aec7-52535d903e7a')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700511 def test_list_images_param_sort(self):
zhufle68f4352020-04-21 13:44:55 +0800512 """Test listing images sorting in descending order"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700513 params = {'sort': 'size:desc'}
514 self._list_sorted_by_image_size_and_assert(params, desc=True)
515
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800516 @decorators.idempotent_id('9faaa0c2-c3a5-43e1-8f61-61c54b409a49')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700517 def test_list_images_param_sort_key_dir(self):
zhufle68f4352020-04-21 13:44:55 +0800518 """Test listing images sorting by size in descending order"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700519 params = {'sort_key': 'size', 'sort_dir': 'desc'}
520 self._list_sorted_by_image_size_and_assert(params, desc=True)
521
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800522 @decorators.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
raiesmh08a1ce3542014-03-04 11:58:29 +0530523 def test_get_image_schema(self):
zhufle68f4352020-04-21 13:44:55 +0800524 """Test to get image schema"""
raiesmh08a1ce3542014-03-04 11:58:29 +0530525 schema = "image"
Ken'ichi Ohmichi190b24e2016-06-07 23:20:09 +0900526 body = self.schemas_client.show_schema(schema)
raiesmh08a1ce3542014-03-04 11:58:29 +0530527 self.assertEqual("image", body['name'])
528
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800529 @decorators.idempotent_id('25c8d7b2-df21-460f-87ac-93130bcdc684')
raiesmh08a1ce3542014-03-04 11:58:29 +0530530 def test_get_images_schema(self):
zhufle68f4352020-04-21 13:44:55 +0800531 """Test to get images schema"""
raiesmh08a1ce3542014-03-04 11:58:29 +0530532 schema = "images"
Ken'ichi Ohmichi190b24e2016-06-07 23:20:09 +0900533 body = self.schemas_client.show_schema(schema)
raiesmh08a1ce3542014-03-04 11:58:29 +0530534 self.assertEqual("images", body['name'])
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700535
536
zhufl6e042bc2017-01-25 10:33:40 +0800537class ListSharedImagesTest(base.BaseV2ImageTest):
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700538 """Here we test the listing of a shared image information"""
539
540 credentials = ['primary', 'alt']
541
542 @classmethod
543 def setup_clients(cls):
544 super(ListSharedImagesTest, cls).setup_clients()
Jordan Pittier8160d312017-04-18 11:52:23 +0200545 cls.image_member_client = cls.os_primary.image_member_client_v2
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700546 cls.alt_img_client = cls.os_alt.image_client_v2
547
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800548 @decorators.idempotent_id('3fa50be4-8e38-4c02-a8db-7811bb780122')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700549 def test_list_images_param_member_status(self):
zhufle68f4352020-04-21 13:44:55 +0800550 """Test listing images by member_status and visibility"""
Steve Lewis8ac5b972016-12-22 07:41:29 -0800551 # Create an image to be shared using default visibility
552 image_file = six.BytesIO(data_utils.random_bytes(2048))
553 container_format = CONF.image.container_formats[0]
554 disk_format = CONF.image.disk_formats[0]
555 image = self.create_image(container_format=container_format,
556 disk_format=disk_format)
557 self.client.store_image_file(image['id'], data=image_file)
558
559 # Share the image created with the alt user
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700560 self.image_member_client.create_image_member(
Steve Lewis8ac5b972016-12-22 07:41:29 -0800561 image_id=image['id'], member=self.alt_img_client.tenant_id)
562
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700563 # As an image consumer you need to provide the member_status parameter
564 # along with the visibility=shared parameter in order for it to show
565 # results
566 params = {'member_status': 'pending', 'visibility': 'shared'}
567 fetched_images = self.alt_img_client.list_images(params)['images']
568 self.assertEqual(1, len(fetched_images))
Steve Lewis8ac5b972016-12-22 07:41:29 -0800569 self.assertEqual(image['id'], fetched_images[0]['id'])