blob: 2432c8b35adf38771f72772c2535e6687eb06c58 [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
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053016import six
Matthew Treinish01472ff2015-02-20 17:26:52 -050017
Sean Dague1937d092013-05-17 16:36:38 -040018from tempest.api.image import base
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -070019from tempest.common import image as common_image
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030020from tempest.common import waiters
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000021from tempest import config
Ken'ichi Ohmichicc01c3e2017-03-10 10:48:14 -080022from tempest.lib.common.utils import data_utils
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -080023from tempest.lib import decorators
Matthew Treinish4217a702016-10-07 17:27:11 -040024from tempest.lib import exceptions
Jay Pipes50677282012-01-06 15:39:20 -050025
Matthew Treinishbc0e03e2014-01-30 16:51:06 +000026CONF = config.CONF
27
Jay Pipes50677282012-01-06 15:39:20 -050028
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090029def get_container_and_disk_format():
30 a_formats = ['ami', 'ari', 'aki']
31
32 container_format = CONF.image.container_formats[0]
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090033
zhufl5aba18f2016-12-27 11:39:31 +080034 # In v1, If container_format is one of ['ami', 'ari', 'aki'], then
35 # disk_format must be same with container_format.
36 # If they are of different item sequence in tempest.conf, such as:
37 # container_formats = ami,ari,aki,bare
38 # disk_formats = ari,ami,aki,vhd
39 # we can select one in disk_format list that is same with container_format.
40 if container_format in a_formats:
41 if container_format in CONF.image.disk_formats:
42 disk_format = container_format
43 else:
44 msg = ("The container format and the disk format don't match. "
45 "Container format: %(container)s, Disk format: %(disk)s." %
lkuchlanead5bf62017-05-23 16:05:45 +030046 {'container': container_format, 'disk':
47 CONF.image.disk_formats})
zhufl5aba18f2016-12-27 11:39:31 +080048 raise exceptions.InvalidConfiguration(msg)
49 else:
50 disk_format = CONF.image.disk_formats[0]
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090051
52 return container_format, disk_format
53
54
Matthew Treinishce3ef922013-03-11 14:02:46 -040055class CreateRegisterImagesTest(base.BaseV1ImageTest):
56 """Here we test the registration and creation of images."""
Jay Pipes50677282012-01-06 15:39:20 -050057
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -080058 @decorators.idempotent_id('3027f8e6-3492-4a11-8575-c3293017af4d')
Jay Pipes50677282012-01-06 15:39:20 -050059 def test_register_then_upload(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050060 # Register, then upload an image
Matthew Treinish72ea4422013-02-07 14:42:49 -050061 properties = {'prop1': 'val1'}
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090062 container_format, disk_format = get_container_and_disk_format()
lkuchlanb3348792016-09-29 10:42:21 +030063 image = self.create_image(name='New Name',
64 container_format=container_format,
65 disk_format=disk_format,
66 is_public=False,
67 properties=properties)
lkuchlanb3348792016-09-29 10:42:21 +030068 self.assertEqual('New Name', image.get('name'))
69 self.assertFalse(image.get('is_public'))
70 self.assertEqual('queued', image.get('status'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050071 for key, val in properties.items():
lkuchlanb3348792016-09-29 10:42:21 +030072 self.assertEqual(val, image.get('properties')[key])
Jay Pipes50677282012-01-06 15:39:20 -050073
74 # Now try uploading an image file
Sirushti Murugesan12dc9732016-07-13 22:49:17 +053075 image_file = six.BytesIO(data_utils.random_bytes())
lkuchlanb3348792016-09-29 10:42:21 +030076 body = self.client.update_image(image['id'], data=image_file)['image']
Attila Fazekase191cb12013-07-29 06:41:52 +020077 self.assertIn('size', body)
Matthew Treinish72ea4422013-02-07 14:42:49 -050078 self.assertEqual(1024, body.get('size'))
Jay Pipes50677282012-01-06 15:39:20 -050079
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -080080 @decorators.idempotent_id('69da74d9-68a9-404b-9664-ff7164ccb0f5')
Jay Pipes50677282012-01-06 15:39:20 -050081 def test_register_remote_image(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -050082 # Register a new remote image
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090083 container_format, disk_format = get_container_and_disk_format()
David Kranz34f18782015-01-06 13:43:55 -050084 body = self.create_image(name='New Remote Image',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090085 container_format=container_format,
86 disk_format=disk_format, is_public=False,
David Kranz34f18782015-01-06 13:43:55 -050087 location=CONF.image.http_image,
88 properties={'key1': 'value1',
89 'key2': 'value2'})
Matthew Treinish72ea4422013-02-07 14:42:49 -050090 self.assertEqual('New Remote Image', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -070091 self.assertFalse(body.get('is_public'))
Matthew Treinish72ea4422013-02-07 14:42:49 -050092 self.assertEqual('active', body.get('status'))
afazekas4a96bf82013-03-25 16:07:38 +010093 properties = body.get('properties')
94 self.assertEqual(properties['key1'], 'value1')
95 self.assertEqual(properties['key2'], 'value2')
Jay Pipes50677282012-01-06 15:39:20 -050096
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -080097 @decorators.idempotent_id('6d0e13a7-515b-460c-b91f-9f4793f09816')
Attila Fazekase72b7cd2013-03-26 18:34:21 +010098 def test_register_http_image(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +090099 container_format, disk_format = get_container_and_disk_format()
lkuchlanb3348792016-09-29 10:42:21 +0300100 image = self.create_image(name='New Http Image',
101 container_format=container_format,
102 disk_format=disk_format, is_public=False,
103 copy_from=CONF.image.http_image)
lkuchlanb3348792016-09-29 10:42:21 +0300104 self.assertEqual('New Http Image', image.get('name'))
105 self.assertFalse(image.get('is_public'))
106 waiters.wait_for_image_status(self.client, image['id'], 'active')
107 self.client.show_image(image['id'])
Attila Fazekase72b7cd2013-03-26 18:34:21 +0100108
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800109 @decorators.idempotent_id('05b19d55-140c-40d0-b36b-fafd774d421b')
hi2suresh75a20302013-04-09 09:17:06 +0000110 def test_register_image_with_min_ram(self):
111 # Register an image with min ram
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900112 container_format, disk_format = get_container_and_disk_format()
hi2suresh75a20302013-04-09 09:17:06 +0000113 properties = {'prop1': 'val1'}
David Kranz34f18782015-01-06 13:43:55 -0500114 body = self.create_image(name='New_image_with_min_ram',
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900115 container_format=container_format,
116 disk_format=disk_format,
David Kranz34f18782015-01-06 13:43:55 -0500117 is_public=False,
118 min_ram=40,
119 properties=properties)
hi2suresh75a20302013-04-09 09:17:06 +0000120 self.assertEqual('New_image_with_min_ram', body.get('name'))
Aaron Rosenc7720622014-05-20 10:38:10 -0700121 self.assertFalse(body.get('is_public'))
hi2suresh75a20302013-04-09 09:17:06 +0000122 self.assertEqual('queued', body.get('status'))
123 self.assertEqual(40, body.get('min_ram'))
124 for key, val in properties.items():
125 self.assertEqual(val, body.get('properties')[key])
David Kranz9c3b3b62014-06-19 16:05:53 -0400126 self.client.delete_image(body['id'])
hi2suresh75a20302013-04-09 09:17:06 +0000127
Jay Pipes50677282012-01-06 15:39:20 -0500128
Matthew Treinishce3ef922013-03-11 14:02:46 -0400129class ListImagesTest(base.BaseV1ImageTest):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000130 """Here we test the listing of image information"""
Jay Pipes50677282012-01-06 15:39:20 -0500131
132 @classmethod
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900133 def skip_checks(cls):
134 super(ListImagesTest, cls).skip_checks()
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200135 if (len(CONF.image.container_formats) < 2 or
136 len(CONF.image.disk_formats) < 2):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900137 skip_msg = ("%s skipped as multiple container formats "
138 "or disk formats are not available." % cls.__name__)
139 raise cls.skipException(skip_msg)
140
141 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100142 def resource_setup(cls):
143 super(ListImagesTest, cls).resource_setup()
Jay Pipes50677282012-01-06 15:39:20 -0500144 # We add a few images here to test the listing functionality of
145 # the images API
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900146 a_formats = ['ami', 'ari', 'aki']
147
148 (cls.container_format,
zhufl7a8f29d2017-02-17 10:16:45 +0800149 container_format_alt) = CONF.image.container_formats[:2]
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900150 cls.disk_format, cls.disk_format_alt = CONF.image.disk_formats[:2]
151 if cls.container_format in a_formats:
152 cls.disk_format = cls.container_format
zhufl7a8f29d2017-02-17 10:16:45 +0800153 if container_format_alt in a_formats:
154 cls.disk_format_alt = container_format_alt
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900155
156 img1 = cls._create_remote_image('one', cls.container_format,
157 cls.disk_format)
zhufl7a8f29d2017-02-17 10:16:45 +0800158 img2 = cls._create_remote_image('two', container_format_alt,
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900159 cls.disk_format_alt)
160 img3 = cls._create_remote_image('dup', cls.container_format,
161 cls.disk_format)
162 img4 = cls._create_remote_image('dup', cls.container_format,
163 cls.disk_format)
zhufl7a8f29d2017-02-17 10:16:45 +0800164 img5 = cls._create_standard_image('1', container_format_alt,
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900165 cls.disk_format_alt, 42)
zhufl7a8f29d2017-02-17 10:16:45 +0800166 img6 = cls._create_standard_image('2', container_format_alt,
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900167 cls.disk_format_alt, 142)
168 img7 = cls._create_standard_image('33', cls.container_format,
169 cls.disk_format, 142)
170 img8 = cls._create_standard_image('33', cls.container_format,
171 cls.disk_format, 142)
Attila Fazekas11795b52013-02-24 15:49:08 +0100172 cls.created_set = set(cls.created_images)
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900173 # same container format
174 cls.same_container_format_set = set((img1, img3, img4, img7, img8))
175 # same disk format
176 cls.same_disk_format_set = set((img2, img5, img6))
177
Attila Fazekas11795b52013-02-24 15:49:08 +0100178 # 1x with size 42
179 cls.size42_set = set((img5,))
180 # 3x with size 142
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800181 cls.size142_set = set((img6, img7, img8,))
Attila Fazekas11795b52013-02-24 15:49:08 +0100182 # dup named
183 cls.dup_set = set((img3, img4))
Jay Pipes50677282012-01-06 15:39:20 -0500184
185 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100186 def _create_remote_image(cls, name, container_format, disk_format):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000187 """Create a new remote image and return newly-registered image-id"""
188
Attila Fazekas11795b52013-02-24 15:49:08 +0100189 name = 'New Remote Image %s' % name
Matthew Treinishe81ae692014-06-19 17:41:31 -0400190 location = CONF.image.http_image
David Kranz34f18782015-01-06 13:43:55 -0500191 image = cls.create_image(name=name,
192 container_format=container_format,
193 disk_format=disk_format,
194 is_public=False,
195 location=location)
lkuchlanb3348792016-09-29 10:42:21 +0300196 return image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500197
198 @classmethod
Attila Fazekas11795b52013-02-24 15:49:08 +0100199 def _create_standard_image(cls, name, container_format,
200 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000201 """Create a new standard image and return newly-registered image-id
202
203 Note that the size of the new image is a random number between
Jay Pipes50677282012-01-06 15:39:20 -0500204 1024 and 4096
205 """
Sirushti Murugesan12dc9732016-07-13 22:49:17 +0530206 image_file = six.BytesIO(data_utils.random_bytes(size))
Attila Fazekas11795b52013-02-24 15:49:08 +0100207 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500208 image = cls.create_image(name=name,
209 container_format=container_format,
210 disk_format=disk_format,
211 is_public=False, data=image_file)
lkuchlanb3348792016-09-29 10:42:21 +0300212 return image['id']
Jay Pipes50677282012-01-06 15:39:20 -0500213
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800214 @decorators.idempotent_id('246178ab-3b33-4212-9a4b-a7fe8261794d')
Jay Pipes50677282012-01-06 15:39:20 -0500215 def test_index_no_params(self):
Sean Dague46c4a2b2013-01-03 17:54:17 -0500216 # Simple test to see all fixture images returned
John Warren66207252015-07-31 15:51:02 -0400217 images_list = self.client.list_images()['images']
Sirushti Murugesan935f2cc2016-07-12 19:48:24 +0530218 image_list = [image['id'] for image in images_list]
Attila Fazekas11795b52013-02-24 15:49:08 +0100219 for image_id in self.created_images:
Attila Fazekase191cb12013-07-29 06:41:52 +0200220 self.assertIn(image_id, image_list)
Attila Fazekas11795b52013-02-24 15:49:08 +0100221
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800222 @decorators.idempotent_id('f1755589-63d6-4468-b098-589820eb4031')
Attila Fazekas11795b52013-02-24 15:49:08 +0100223 def test_index_disk_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900224 images_list = self.client.list_images(
225 disk_format=self.disk_format_alt)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100226 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900227 self.assertEqual(image['disk_format'], self.disk_format_alt)
Attila Fazekas11795b52013-02-24 15:49:08 +0100228 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900229 self.assertTrue(self.same_disk_format_set <= result_set)
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200230 self.assertFalse(self.created_set - self.same_disk_format_set <=
231 result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100232
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800233 @decorators.idempotent_id('2143655d-96d9-4bec-9188-8674206b4b3b')
Attila Fazekas11795b52013-02-24 15:49:08 +0100234 def test_index_container_format(self):
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900235 images_list = self.client.list_images(
236 container_format=self.container_format)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100237 for image in images_list:
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900238 self.assertEqual(image['container_format'], self.container_format)
Attila Fazekas11795b52013-02-24 15:49:08 +0100239 result_set = set(map(lambda x: x['id'], images_list))
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900240 self.assertTrue(self.same_container_format_set <= result_set)
Federico Ressi2d6bcaa2018-04-11 12:37:36 +0200241 self.assertFalse(self.created_set - self.same_container_format_set <=
242 result_set)
Attila Fazekas11795b52013-02-24 15:49:08 +0100243
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800244 @decorators.idempotent_id('feb32ac6-22bb-4a16-afd8-9454bb714b14')
Attila Fazekas11795b52013-02-24 15:49:08 +0100245 def test_index_max_size(self):
John Warren66207252015-07-31 15:51:02 -0400246 images_list = self.client.list_images(size_max=42)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100247 for image in images_list:
Béla Vancsics64862f72016-11-08 09:12:31 +0100248 self.assertLessEqual(image['size'], 42)
Attila Fazekas11795b52013-02-24 15:49:08 +0100249 result_set = set(map(lambda x: x['id'], images_list))
250 self.assertTrue(self.size42_set <= result_set)
251 self.assertFalse(self.created_set - self.size42_set <= result_set)
252
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800253 @decorators.idempotent_id('6ffc16d0-4cbf-4401-95c8-4ac63eac34d8')
Attila Fazekas11795b52013-02-24 15:49:08 +0100254 def test_index_min_size(self):
John Warren66207252015-07-31 15:51:02 -0400255 images_list = self.client.list_images(size_min=142)['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100256 for image in images_list:
zhufl080dcfb2016-10-21 17:45:38 +0800257 self.assertGreaterEqual(image['size'], 142)
Attila Fazekas11795b52013-02-24 15:49:08 +0100258 result_set = set(map(lambda x: x['id'], images_list))
259 self.assertTrue(self.size142_set <= result_set)
260 self.assertFalse(self.size42_set <= result_set)
261
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800262 @decorators.idempotent_id('e5dc26d9-9aa2-48dd-bda5-748e1445da98')
Attila Fazekas11795b52013-02-24 15:49:08 +0100263 def test_index_status_active_detail(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000264 images_list = self.client.list_images(detail=True,
265 status='active',
266 sort_key='size',
John Warren66207252015-07-31 15:51:02 -0400267 sort_dir='desc')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100268 top_size = images_list[0]['size'] # We have non-zero sized images
269 for image in images_list:
270 size = image['size']
Béla Vancsics64862f72016-11-08 09:12:31 +0100271 self.assertLessEqual(size, top_size)
Attila Fazekas11795b52013-02-24 15:49:08 +0100272 top_size = size
273 self.assertEqual(image['status'], 'active')
274
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800275 @decorators.idempotent_id('097af10a-bae8-4342-bff4-edf89969ed2a')
Attila Fazekas11795b52013-02-24 15:49:08 +0100276 def test_index_name(self):
Ken'ichi Ohmichibcad2a22015-05-22 09:37:06 +0000277 images_list = self.client.list_images(
278 detail=True,
John Warren66207252015-07-31 15:51:02 -0400279 name='New Remote Image dup')['images']
Attila Fazekas11795b52013-02-24 15:49:08 +0100280 result_set = set(map(lambda x: x['id'], images_list))
281 for image in images_list:
282 self.assertEqual(image['name'], 'New Remote Image dup')
283 self.assertTrue(self.dup_set <= result_set)
284 self.assertFalse(self.created_set - self.dup_set <= result_set)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800285
286
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800287class UpdateImageMetaTest(base.BaseV1ImageTest):
288 @classmethod
Andrea Frittoli69a6b632014-09-15 13:14:53 +0100289 def resource_setup(cls):
290 super(UpdateImageMetaTest, cls).resource_setup()
Takashi NATSUMEb7d85912015-11-10 13:24:48 +0900291 container_format, disk_format = get_container_and_disk_format()
292 cls.image_id = cls._create_standard_image('1', container_format,
293 disk_format, 42)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800294
295 @classmethod
296 def _create_standard_image(cls, name, container_format,
297 disk_format, size):
Ken'ichi Ohmichi9e3dac02015-11-19 07:01:07 +0000298 """Create a new standard image and return newly-registered image-id"""
299
Sirushti Murugesan12dc9732016-07-13 22:49:17 +0530300 image_file = six.BytesIO(data_utils.random_bytes(size))
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800301 name = 'New Standard Image %s' % name
David Kranz34f18782015-01-06 13:43:55 -0500302 image = cls.create_image(name=name,
303 container_format=container_format,
304 disk_format=disk_format,
305 is_public=False, data=image_file,
306 properties={'key1': 'value1'})
lkuchlanb3348792016-09-29 10:42:21 +0300307 return image['id']
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800308
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800309 @decorators.idempotent_id('01752c1c-0275-4de3-9e5b-876e44541928')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800310 def test_list_image_metadata(self):
311 # All metadata key/value pairs for an image should be returned
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -0700312 resp = self.client.check_image(self.image_id)
313 resp_metadata = common_image.get_image_meta_from_headers(resp)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800314 expected = {'key1': 'value1'}
315 self.assertEqual(expected, resp_metadata['properties'])
316
Ken'ichi Ohmichif35efa22017-01-27 17:55:24 -0800317 @decorators.idempotent_id('d6d7649c-08ce-440d-9ea7-e3dda552f33c')
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800318 def test_update_image_metadata(self):
319 # The metadata for the image should match the updated values
320 req_metadata = {'key1': 'alt1', 'key2': 'value2'}
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -0700321 resp = self.client.check_image(self.image_id)
322 metadata = common_image.get_image_meta_from_headers(resp)
ivan-zhud1bbe5d2013-12-29 18:32:46 +0800323 self.assertEqual(metadata['properties'], {'key1': 'value1'})
324 metadata['properties'].update(req_metadata)
Ken'ichi Ohmichi02bcdf32016-06-17 16:41:26 -0700325 headers = common_image.image_meta_to_headers(
326 properties=metadata['properties'])
guo yunxian6c5f5eb2016-08-23 15:35:53 +0800327 self.client.update_image(self.image_id, headers=headers)
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -0700328 resp = self.client.check_image(self.image_id)
329 resp_metadata = common_image.get_image_meta_from_headers(resp)
guo yunxian6c5f5eb2016-08-23 15:35:53 +0800330 self.assertEqual(req_metadata, resp_metadata['properties'])