blob: d1f6f983d987e3e04139a670128bb18427629530 [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'],
Dan Smith8dfefce2021-01-14 12:15:45 -0800161 six.BytesIO(data_utils.random_bytes()))
PranaliD491d63e2020-08-18 13:29:21 +0000162 # 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)
zhufl940a9e22020-11-25 15:36:13 +0800405 sorted_list = [image['size'] for image in images_list
406 if image['size'] is not None]
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700407 msg = 'The list of images was not sorted correctly.'
408 self.assertEqual(sorted(sorted_list, reverse=desc), sorted_list, msg)
409
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800410 @decorators.idempotent_id('1e341d7a-90a9-494c-b143-2cdf2aeb6aee')
Flavio Percoco7e26be12015-09-15 22:33:19 +0200411 def test_list_no_params(self):
zhufle68f4352020-04-21 13:44:55 +0800412 """Simple test to see all fixture images returned"""
John Warrenf3b3e952015-08-17 19:28:12 +0000413 images_list = self.client.list_images()['images']
Sirushti Murugesan935f2cc2016-07-12 19:48:24 +0530414 image_list = [image['id'] for image in images_list]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700415
Matthew Treinisha62347f2013-03-01 16:37:30 -0500416 for image in self.created_images:
Attila Fazekase191cb12013-07-29 06:41:52 +0200417 self.assertIn(image, image_list)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700418
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800419 @decorators.idempotent_id('9959ca1d-1aa7-4b7a-a1ea-0fff0499b37e')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700420 def test_list_images_param_container_format(self):
zhufle68f4352020-04-21 13:44:55 +0800421 """Test to get all images with a specific container_format"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700422 params = {"container_format": self.test_data['container_format']}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700423 self._list_by_param_value_and_assert(params)
424
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800425 @decorators.idempotent_id('4a4735a7-f22f-49b6-b0d9-66e1ef7453eb')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700426 def test_list_images_param_disk_format(self):
zhufle68f4352020-04-21 13:44:55 +0800427 """Test to get all images with disk_format = raw"""
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700428 params = {"disk_format": "raw"}
429 self._list_by_param_value_and_assert(params)
430
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800431 @decorators.idempotent_id('7a95bb92-d99e-4b12-9718-7bc6ab73e6d2')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700432 def test_list_images_param_visibility(self):
zhufle68f4352020-04-21 13:44:55 +0800433 """Test to get all images with visibility = private"""
Aaron Rosenc7720622014-05-20 10:38:10 -0700434 params = {"visibility": "private"}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700435 self._list_by_param_value_and_assert(params)
436
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800437 @decorators.idempotent_id('cf1b9a48-8340-480e-af7b-fe7e17690876')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700438 def test_list_images_param_size(self):
zhufle68f4352020-04-21 13:44:55 +0800439 """Test to get all images by size"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900440 image_id = self.created_images[0]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700441 # Get image metadata
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000442 image = self.client.show_image(image_id)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700443
444 params = {"size": image['size']}
445 self._list_by_param_value_and_assert(params)
446
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800447 @decorators.idempotent_id('4ad8c157-971a-4ba8-aa84-ed61154b1e7f')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700448 def test_list_images_param_min_max_size(self):
zhufle68f4352020-04-21 13:44:55 +0800449 """Test to get all images with min size and max size"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900450 image_id = self.created_images[0]
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700451 # Get image metadata
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000452 image = self.client.show_image(image_id)
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700453
454 size = image['size']
455 params = {"size_min": size - 500, "size_max": size + 500}
John Warrenf3b3e952015-08-17 19:28:12 +0000456 images_list = self.client.list_images(params=params)['images']
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700457 image_size_list = map(lambda x: x['size'], images_list)
458
459 for image_size in image_size_list:
Béla Vancsics64862f72016-11-08 09:12:31 +0100460 self.assertGreaterEqual(image_size, params['size_min'],
461 "Failed to get images by size_min")
462 self.assertLessEqual(image_size, params['size_max'],
463 "Failed to get images by size_max")
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700464
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800465 @decorators.idempotent_id('7fc9e369-0f58-4d05-9aa5-0969e2d59d15')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700466 def test_list_images_param_status(self):
zhufle68f4352020-04-21 13:44:55 +0800467 """Test to get all active images"""
Anju Tiwarica2249d2014-01-23 17:33:02 +0530468 params = {"status": "active"}
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700469 self._list_by_param_value_and_assert(params)
470
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800471 @decorators.idempotent_id('e914a891-3cc8-4b40-ad32-e0a39ffbddbb')
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700472 def test_list_images_param_limit(self):
zhufle68f4352020-04-21 13:44:55 +0800473 """Test to get images by limit"""
Takashi NATSUME12a48512015-08-10 18:33:16 +0900474 params = {"limit": 1}
John Warrenf3b3e952015-08-17 19:28:12 +0000475 images_list = self.client.list_images(params=params)['images']
Abhijeet Malawadef268d8e2013-09-17 06:20:23 -0700476
477 self.assertEqual(len(images_list), params['limit'],
478 "Failed to get images by limit")
raiesmh08a1ce3542014-03-04 11:58:29 +0530479
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800480 @decorators.idempotent_id('e9a44b91-31c8-4b40-a332-e0a39ffb4dbb')
Li Wei14bf2412016-09-25 15:56:23 +0800481 def test_list_image_param_owner(self):
zhufle68f4352020-04-21 13:44:55 +0800482 """Test to get images by owner"""
Li Wei14bf2412016-09-25 15:56:23 +0800483 image_id = self.created_images[0]
484 # Get image metadata
485 image = self.client.show_image(image_id)
486
487 params = {"owner": image['owner']}
488 self._list_by_param_value_and_assert(params)
489
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800490 @decorators.idempotent_id('55c8f5f5-bfed-409d-a6d5-4caeda985d7b')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700491 def test_list_images_param_name(self):
zhufle68f4352020-04-21 13:44:55 +0800492 """Test to get images by name"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700493 params = {'name': self.test_data['name']}
494 self._list_by_param_value_and_assert(params)
495
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800496 @decorators.idempotent_id('aa8ac4df-cff9-418b-8d0f-dd9c67b072c9')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700497 def test_list_images_param_tag(self):
zhufle68f4352020-04-21 13:44:55 +0800498 """Test to get images matching a tag"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700499 params = {'tag': self.test_data['tags'][0]}
500 images_list = self.client.list_images(params=params)['images']
501 # Validating properties of fetched images
502 self.assertNotEmpty(images_list)
503 for image in images_list:
504 msg = ("The image {image_name} does not have the expected tag "
505 "{expected_tag} among its tags: {observerd_tags}."
506 .format(image_name=image['name'],
507 expected_tag=self.test_data['tags'][0],
508 observerd_tags=image['tags']))
509 self.assertIn(self.test_data['tags'][0], image['tags'], msg)
510
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800511 @decorators.idempotent_id('eeadce49-04e0-43b7-aec7-52535d903e7a')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700512 def test_list_images_param_sort(self):
zhufle68f4352020-04-21 13:44:55 +0800513 """Test listing images sorting in descending order"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700514 params = {'sort': 'size:desc'}
515 self._list_sorted_by_image_size_and_assert(params, desc=True)
516
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800517 @decorators.idempotent_id('9faaa0c2-c3a5-43e1-8f61-61c54b409a49')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700518 def test_list_images_param_sort_key_dir(self):
zhufle68f4352020-04-21 13:44:55 +0800519 """Test listing images sorting by size in descending order"""
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700520 params = {'sort_key': 'size', 'sort_dir': 'desc'}
521 self._list_sorted_by_image_size_and_assert(params, desc=True)
522
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800523 @decorators.idempotent_id('622b925c-479f-4736-860d-adeaf13bc371')
raiesmh08a1ce3542014-03-04 11:58:29 +0530524 def test_get_image_schema(self):
zhufle68f4352020-04-21 13:44:55 +0800525 """Test to get image schema"""
raiesmh08a1ce3542014-03-04 11:58:29 +0530526 schema = "image"
Ken'ichi Ohmichi190b24e2016-06-07 23:20:09 +0900527 body = self.schemas_client.show_schema(schema)
raiesmh08a1ce3542014-03-04 11:58:29 +0530528 self.assertEqual("image", body['name'])
529
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800530 @decorators.idempotent_id('25c8d7b2-df21-460f-87ac-93130bcdc684')
raiesmh08a1ce3542014-03-04 11:58:29 +0530531 def test_get_images_schema(self):
zhufle68f4352020-04-21 13:44:55 +0800532 """Test to get images schema"""
raiesmh08a1ce3542014-03-04 11:58:29 +0530533 schema = "images"
Ken'ichi Ohmichi190b24e2016-06-07 23:20:09 +0900534 body = self.schemas_client.show_schema(schema)
raiesmh08a1ce3542014-03-04 11:58:29 +0530535 self.assertEqual("images", body['name'])
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700536
537
zhufl6e042bc2017-01-25 10:33:40 +0800538class ListSharedImagesTest(base.BaseV2ImageTest):
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700539 """Here we test the listing of a shared image information"""
540
541 credentials = ['primary', 'alt']
542
543 @classmethod
544 def setup_clients(cls):
545 super(ListSharedImagesTest, cls).setup_clients()
Jordan Pittier8160d312017-04-18 11:52:23 +0200546 cls.image_member_client = cls.os_primary.image_member_client_v2
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700547 cls.alt_img_client = cls.os_alt.image_client_v2
548
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800549 @decorators.idempotent_id('3fa50be4-8e38-4c02-a8db-7811bb780122')
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700550 def test_list_images_param_member_status(self):
zhufle68f4352020-04-21 13:44:55 +0800551 """Test listing images by member_status and visibility"""
Steve Lewis8ac5b972016-12-22 07:41:29 -0800552 # Create an image to be shared using default visibility
553 image_file = six.BytesIO(data_utils.random_bytes(2048))
554 container_format = CONF.image.container_formats[0]
555 disk_format = CONF.image.disk_formats[0]
556 image = self.create_image(container_format=container_format,
557 disk_format=disk_format)
558 self.client.store_image_file(image['id'], data=image_file)
559
560 # Share the image created with the alt user
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700561 self.image_member_client.create_image_member(
Steve Lewis8ac5b972016-12-22 07:41:29 -0800562 image_id=image['id'], member=self.alt_img_client.tenant_id)
563
Castulo J. Martineze9c8ce82016-05-16 07:55:53 -0700564 # As an image consumer you need to provide the member_status parameter
565 # along with the visibility=shared parameter in order for it to show
566 # results
567 params = {'member_status': 'pending', 'visibility': 'shared'}
568 fetched_images = self.alt_img_client.list_images(params)['images']
569 self.assertEqual(1, len(fetched_images))
Steve Lewis8ac5b972016-12-22 07:41:29 -0800570 self.assertEqual(image['id'], fetched_images[0]['id'])