Move image_meta_to_headers from images_client
Glance v1 images_client contains image_meta_to_headers() which
converts a dict to headers. However, most service clients'
methods don't convert like that.
Then this moves image_meta_to_headers() to common place like
the compute module from the service client.
Partially implements blueprint consistent-service-method-names
Change-Id: Id8e47fd35f7667578854bc439238a4b0f36fbb8f
diff --git a/tempest/api/compute/images/test_image_metadata.py b/tempest/api/compute/images/test_image_metadata.py
index 427a748..6f80730 100644
--- a/tempest/api/compute/images/test_image_metadata.py
+++ b/tempest/api/compute/images/test_image_metadata.py
@@ -16,6 +16,7 @@
import six
from tempest.api.compute import base
+from tempest.common import image as common_image
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
@@ -55,15 +56,18 @@
super(ImagesMetadataTestJSON, cls).resource_setup()
cls.image_id = None
- name = data_utils.rand_name('image')
+ params = {
+ 'name': data_utils.rand_name('image'),
+ 'container_format': 'bare',
+ 'disk_format': 'raw'
+ }
if CONF.image_feature_enabled.api_v1:
- kwargs = dict(is_public=False)
+ params.update({'is_public': False})
+ params = {'headers': common_image.image_meta_to_headers(**params)}
else:
- kwargs = dict(visibility='private')
- body = cls.glance_client.create_image(name=name,
- container_format='bare',
- disk_format='raw',
- **kwargs)
+ params.update({'visibility': 'private'})
+
+ body = cls.glance_client.create_image(**params)
body = body['image'] if 'image' in body else body
cls.image_id = body['id']
cls.images.append(cls.image_id)
diff --git a/tempest/api/compute/images/test_list_image_filters.py b/tempest/api/compute/images/test_list_image_filters.py
index e74ca67..9017461 100644
--- a/tempest/api/compute/images/test_list_image_filters.py
+++ b/tempest/api/compute/images/test_list_image_filters.py
@@ -19,6 +19,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import image as common_image
from tempest.common.utils import data_utils
from tempest.common import waiters
from tempest import config
@@ -58,15 +59,19 @@
super(ListImageFiltersTestJSON, cls).resource_setup()
def _create_image():
- name = data_utils.rand_name('image')
+ params = {
+ 'name': data_utils.rand_name('image'),
+ 'container_format': 'bare',
+ 'disk_format': 'raw'
+ }
if CONF.image_feature_enabled.api_v1:
- kwargs = dict(is_public=False)
+ params.update({'is_public': False})
+ params = {'headers':
+ common_image.image_meta_to_headers(**params)}
else:
- kwargs = dict(visibility='private')
- body = cls.glance_client.create_image(name=name,
- container_format='bare',
- disk_format='raw',
- **kwargs)
+ params.update({'visibility': 'private'})
+
+ body = cls.glance_client.create_image(**params)
body = body['image'] if 'image' in body else body
image_id = body['id']
cls.images.append(image_id)
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 3fefc81..6fd6ea6 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -14,6 +14,7 @@
from six import moves
+from tempest.common import image as common_image
from tempest.common.utils import data_utils
from tempest import config
from tempest.lib.common.utils import test_utils
@@ -55,14 +56,20 @@
super(BaseImageTest, cls).resource_cleanup()
@classmethod
- def create_image(cls, **kwargs):
+ def create_image(cls, data=None, **kwargs):
"""Wrapper that returns a test image."""
if 'name' not in kwargs:
name = data_utils.rand_name(cls.__name__ + "-instance")
kwargs['name'] = name
- image = cls.client.create_image(**kwargs)
+ params = cls._get_create_params(**kwargs)
+ if data:
+ # NOTE: On glance v1 API, the data should be passed on
+ # a header. Then here handles the data separately.
+ params['data'] = data
+
+ image = cls.client.create_image(**params)
# Image objects returned by the v1 client have the image
# data inside a dict that is keyed against 'image'.
if 'image' in image:
@@ -70,6 +77,10 @@
cls.created_images.append(image['id'])
return image
+ @classmethod
+ def _get_create_params(cls, **kwargs):
+ return kwargs
+
class BaseV1ImageTest(BaseImageTest):
@@ -85,6 +96,10 @@
super(BaseV1ImageTest, cls).setup_clients()
cls.client = cls.os.image_client
+ @classmethod
+ def _get_create_params(cls, **kwargs):
+ return {'headers': common_image.image_meta_to_headers(**kwargs)}
+
class BaseV1ImageMembersTest(BaseV1ImageTest):
diff --git a/tempest/api/image/v1/test_images.py b/tempest/api/image/v1/test_images.py
index 59ac646..def7750 100644
--- a/tempest/api/image/v1/test_images.py
+++ b/tempest/api/image/v1/test_images.py
@@ -320,8 +320,10 @@
metadata = common_image.get_image_meta_from_headers(resp)
self.assertEqual(metadata['properties'], {'key1': 'value1'})
metadata['properties'].update(req_metadata)
- metadata = self.client.update_image(
- self.image_id, properties=metadata['properties'])['image']
+ headers = common_image.image_meta_to_headers(
+ properties=metadata['properties'])
+ metadata = self.client.update_image(self.image_id,
+ headers=headers)['image']
resp = self.client.check_image(self.image_id)
resp_metadata = common_image.get_image_meta_from_headers(resp)
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index babee74..9e67c25 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -27,17 +27,17 @@
def test_register_with_invalid_container_format(self):
# Negative tests for invalid data supplied to POST /images
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
- name='test',
- container_format='wrong',
- disk_format='vhd',)
+ headers={'x-image-meta-name': 'test',
+ 'x-image-meta-container_format': 'wrong',
+ 'x-image-meta-disk_format': 'vhd'})
@test.attr(type=['negative'])
@test.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
def test_register_with_invalid_disk_format(self):
self.assertRaises(lib_exc.BadRequest, self.client.create_image,
- name='test',
- container_format='bare',
- disk_format='wrong',)
+ headers={'x-image-meta-name': 'test',
+ 'x-image-meta-container_format': 'bare',
+ 'x-image-meta-disk_format': 'wrong'})
@test.attr(type=['negative'])
@test.idempotent_id('bb016f15-0820-4f27-a92d-09b2f67d2488')
diff --git a/tempest/common/image.py b/tempest/common/image.py
index 42ce5ac..72e3a72 100644
--- a/tempest/common/image.py
+++ b/tempest/common/image.py
@@ -13,6 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+import six
+
def get_image_meta_from_headers(resp):
meta = {'properties': {}}
@@ -36,3 +40,23 @@
except ValueError:
pass
return meta
+
+
+def image_meta_to_headers(**metadata):
+ headers = {}
+ fields_copy = copy.deepcopy(metadata)
+
+ copy_from = fields_copy.pop('copy_from', None)
+ if copy_from is not None:
+ headers['x-glance-api-copy-from'] = copy_from
+
+ for key, value in six.iteritems(fields_copy.pop('properties', {})):
+ headers['x-image-meta-property-%s' % key] = str(value)
+
+ for key, value in six.iteritems(fields_copy.pop('api', {})):
+ headers['x-glance-api-property-%s' % key] = str(value)
+
+ for key, value in six.iteritems(fields_copy):
+ headers['x-image-meta-%s' % key] = str(value)
+
+ return headers
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index dd6e0e5..11c96e0 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -388,6 +388,7 @@
if CONF.image_feature_enabled.api_v1:
params['is_public'] = 'False'
params['properties'] = properties
+ params = {'headers': common_image.image_meta_to_headers(**params)}
else:
params['visibility'] = 'private'
# Additional properties are flattened out in the v2 API.
diff --git a/tempest/services/image/v1/json/images_client.py b/tempest/services/image/v1/json/images_client.py
index ed0a676..0db98f8 100644
--- a/tempest/services/image/v1/json/images_client.py
+++ b/tempest/services/image/v1/json/images_client.py
@@ -13,11 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import copy
import functools
from oslo_serialization import jsonutils as json
-import six
from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
@@ -29,20 +27,6 @@
class ImagesClient(rest_client.RestClient):
api_version = "v1"
- def _image_meta_to_headers(self, fields):
- headers = {}
- fields_copy = copy.deepcopy(fields)
- copy_from = fields_copy.pop('copy_from', None)
- if copy_from is not None:
- headers['x-glance-api-copy-from'] = copy_from
- for key, value in six.iteritems(fields_copy.pop('properties', {})):
- headers['x-image-meta-property-%s' % key] = str(value)
- for key, value in six.iteritems(fields_copy.pop('api', {})):
- headers['x-glance-api-property-%s' % key] = str(value)
- for key, value in six.iteritems(fields_copy):
- headers['x-image-meta-%s' % key] = str(value)
- return headers
-
def _create_with_data(self, headers, data):
# We are going to do chunked transfert, so split the input data
# info fixed-sized chunks.
@@ -74,14 +58,14 @@
self._http = self._get_http()
return self._http
- def create_image(self, data=None, **kwargs):
+ def create_image(self, data=None, headers=None):
"""Create an image.
Available params: http://developer.openstack.org/
api-ref-image-v1.html#createImage-v1
"""
- headers = {}
- headers.update(self._image_meta_to_headers(kwargs))
+ if headers is None:
+ headers = {}
if data is not None:
return self._create_with_data(headers, data)
@@ -91,14 +75,14 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
- def update_image(self, image_id, data=None, **kwargs):
+ def update_image(self, image_id, data=None, headers=None):
"""Update an image.
Available params: http://developer.openstack.org/
api-ref-image-v1.html#updateImage-v1
"""
- headers = {}
- headers.update(self._image_meta_to_headers(kwargs))
+ if headers is None:
+ headers = {}
if data is not None:
return self._update_with_data(image_id, headers, data)
diff --git a/tempest/tests/common/test_image.py b/tempest/tests/common/test_image.py
index fdd0ae8..34772a2 100644
--- a/tempest/tests/common/test_image.py
+++ b/tempest/tests/common/test_image.py
@@ -38,3 +38,22 @@
'name': 'New Http Image'
}
self.assertEqual(expected, observed)
+
+ def test_image_meta_to_headers(self):
+ observed = image.image_meta_to_headers(
+ name='test',
+ container_format='wrong',
+ disk_format='vhd',
+ copy_from='http://localhost/images/10',
+ properties={'foo': 'bar'},
+ api={'abc': 'def'})
+
+ expected = {
+ 'x-image-meta-name': 'test',
+ 'x-image-meta-container_format': 'wrong',
+ 'x-image-meta-disk_format': 'vhd',
+ 'x-glance-api-copy-from': 'http://localhost/images/10',
+ 'x-image-meta-property-foo': 'bar',
+ 'x-glance-api-property-abc': 'def'
+ }
+ self.assertEqual(expected, observed)