Drop deprecated Glance V1 API support
Glance V1 API was deprecated in Stein release in Horizon and deprecated in Glance since Newton release. Change-Id: I18f6fd03dd3e07fa4f2ccfdccfdc3ca766c91c16
This commit is contained in:
parent
cf904d1194
commit
6037a58c6e
@ -30,7 +30,7 @@ from django.core.files.uploadedfile import InMemoryUploadedFile
|
|||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
from django.core.files.uploadedfile import TemporaryUploadedFile
|
from django.core.files.uploadedfile import TemporaryUploadedFile
|
||||||
|
|
||||||
import glanceclient as glance_client
|
from glanceclient.v2 import client
|
||||||
import six
|
import six
|
||||||
from six.moves import _thread as thread
|
from six.moves import _thread as thread
|
||||||
|
|
||||||
@ -52,20 +52,8 @@ else:
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
VERSIONS = base.APIVersionManager("image", preferred_version=2)
|
VERSIONS = base.APIVersionManager("image", preferred_version=2)
|
||||||
|
|
||||||
try:
|
VERSIONS.load_supported_version(2, {"client": client,
|
||||||
# pylint: disable=ungrouped-imports
|
|
||||||
from glanceclient.v2 import client as glance_client_v2
|
|
||||||
VERSIONS.load_supported_version(2, {"client": glance_client_v2,
|
|
||||||
"version": 2})
|
"version": 2})
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
# pylint: disable=ungrouped-imports
|
|
||||||
from glanceclient.v1 import client as glance_client_v1
|
|
||||||
VERSIONS.load_supported_version(1, {"client": glance_client_v1,
|
|
||||||
"version": 1})
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# TODO(e0ne): remove this workaround once glanceclient will raise
|
# TODO(e0ne): remove this workaround once glanceclient will raise
|
||||||
# RequestURITooLong exception
|
# RequestURITooLong exception
|
||||||
@ -91,9 +79,8 @@ class Image(base.APIResourceWrapper):
|
|||||||
def __getattribute__(self, attr):
|
def __getattribute__(self, attr):
|
||||||
# Because Glance v2 treats custom properties as normal
|
# Because Glance v2 treats custom properties as normal
|
||||||
# attributes, we need to be more flexible than the resource
|
# attributes, we need to be more flexible than the resource
|
||||||
# wrappers usually allow. In v1 they were defined under a
|
# wrappers usually allow.
|
||||||
# "properties" attribute.
|
if attr == "properties":
|
||||||
if VERSIONS.active >= 2 and attr == "properties":
|
|
||||||
return {k: v for (k, v) in self._apiresource.items()
|
return {k: v for (k, v) in self._apiresource.items()
|
||||||
if self.property_visible(k)}
|
if self.property_visible(k)}
|
||||||
try:
|
try:
|
||||||
@ -130,10 +117,6 @@ class Image(base.APIResourceWrapper):
|
|||||||
return prop_name not in (self._attrs | self._ext_attrs)
|
return prop_name not in (self._attrs | self._ext_attrs)
|
||||||
|
|
||||||
def to_dict(self, show_ext_attrs=False):
|
def to_dict(self, show_ext_attrs=False):
|
||||||
# When using v1 Image objects (including when running unit tests
|
|
||||||
# for v2), self._apiresource is not iterable. In that case,
|
|
||||||
# the properties are included in the apiresource dict, so
|
|
||||||
# just return that dict.
|
|
||||||
if not isinstance(self._apiresource, Iterable):
|
if not isinstance(self._apiresource, Iterable):
|
||||||
return self._apiresource.to_dict()
|
return self._apiresource.to_dict()
|
||||||
image_dict = super(Image, self).to_dict()
|
image_dict = super(Image, self).to_dict()
|
||||||
@ -151,22 +134,15 @@ class Image(base.APIResourceWrapper):
|
|||||||
|
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def glanceclient(request, version=None):
|
def glanceclient(request):
|
||||||
api_version = VERSIONS.get_active_version()
|
api_version = VERSIONS.get_active_version()
|
||||||
|
|
||||||
url = base.url_for(request, 'image')
|
url = base.url_for(request, 'image')
|
||||||
insecure = settings.OPENSTACK_SSL_NO_VERIFY
|
insecure = settings.OPENSTACK_SSL_NO_VERIFY
|
||||||
cacert = settings.OPENSTACK_SSL_CACERT
|
cacert = settings.OPENSTACK_SSL_CACERT
|
||||||
|
|
||||||
# TODO(jpichon): Temporarily keep both till we update the API calls
|
|
||||||
# to stop hardcoding a version in this file. Once that's done we
|
|
||||||
# can get rid of the deprecated 'version' parameter.
|
|
||||||
if version is None:
|
|
||||||
return api_version['client'].Client(url, token=request.user.token.id,
|
return api_version['client'].Client(url, token=request.user.token.id,
|
||||||
insecure=insecure, cacert=cacert)
|
insecure=insecure, cacert=cacert)
|
||||||
else:
|
|
||||||
return glance_client.Client(version, url, token=request.user.token.id,
|
|
||||||
insecure=insecure, cacert=cacert)
|
|
||||||
|
|
||||||
|
|
||||||
# Note: Glance is adding more than just public and private in Newton or later
|
# Note: Glance is adding more than just public and private in Newton or later
|
||||||
@ -193,75 +169,30 @@ def _normalize_is_public_filter(filters):
|
|||||||
if not filters:
|
if not filters:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Glance v1 uses filter 'is_public' (True, False).
|
|
||||||
# Glance v2 uses filter 'visibility' ('public', 'private', ...).
|
# Glance v2 uses filter 'visibility' ('public', 'private', ...).
|
||||||
if VERSIONS.active >= 2:
|
|
||||||
if 'is_public' in filters:
|
if 'is_public' in filters:
|
||||||
# Glance v2: Replace 'is_public' with 'visibility'.
|
# Glance v2: Replace 'is_public' with 'visibility'.
|
||||||
visibility = PUBLIC_TO_VISIBILITY_MAP[filters['is_public']]
|
visibility = PUBLIC_TO_VISIBILITY_MAP[filters['is_public']]
|
||||||
del filters['is_public']
|
del filters['is_public']
|
||||||
if visibility is not None:
|
if visibility is not None:
|
||||||
filters['visibility'] = visibility
|
filters['visibility'] = visibility
|
||||||
elif 'visibility' in filters:
|
|
||||||
# Glance v1: Replace 'visibility' with 'is_public'.
|
|
||||||
filters['is_public'] = filters['visibility'] == "public"
|
|
||||||
del filters['visibility']
|
|
||||||
|
|
||||||
|
|
||||||
def _normalize_owner_id_filter(filters):
|
def _normalize_owner_id_filter(filters):
|
||||||
if not filters:
|
if not filters:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Glance v1 uses filter 'property-owner_id' (Project ID).
|
|
||||||
# Glance v2 uses filter 'owner' (Project ID).
|
# Glance v2 uses filter 'owner' (Project ID).
|
||||||
if VERSIONS.active >= 2:
|
|
||||||
if 'property-owner_id' in filters:
|
if 'property-owner_id' in filters:
|
||||||
# Glance v2: Replace 'property-owner_id' with 'owner'.
|
# Glance v2: Replace 'property-owner_id' with 'owner'.
|
||||||
filters['owner'] = filters['property-owner_id']
|
filters['owner'] = filters['property-owner_id']
|
||||||
del filters['property-owner_id']
|
del filters['property-owner_id']
|
||||||
elif 'owner' in filters:
|
|
||||||
# Glance v1: Replace 'owner' with 'property-owner_id'.
|
|
||||||
filters['property-owner_id'] = filters['owner']
|
|
||||||
del filters['owner']
|
|
||||||
|
|
||||||
|
|
||||||
def _normalize_list_input(filters, **kwargs):
|
def _normalize_list_input(filters, **kwargs):
|
||||||
_normalize_is_public_filter(filters)
|
_normalize_is_public_filter(filters)
|
||||||
_normalize_owner_id_filter(filters)
|
_normalize_owner_id_filter(filters)
|
||||||
|
|
||||||
if VERSIONS.active < 2:
|
|
||||||
# Glance v1 client processes some keywords specifically.
|
|
||||||
# Others, it just takes as a nested dict called filters.
|
|
||||||
# This results in the following being passed into the glance client:
|
|
||||||
# {
|
|
||||||
# 'is_public': u'true',
|
|
||||||
# 'sort_key': u'name',
|
|
||||||
# 'sort_dir': u'asc',
|
|
||||||
# 'filters': {
|
|
||||||
# u'min_disk': u'0',
|
|
||||||
# u'name': u'mysql',
|
|
||||||
# 'properties': {
|
|
||||||
# u'os_shutdown_timeout': u'1'
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
v1_keywords = ['page_size', 'limit', 'sort_dir', 'sort_key', 'marker',
|
|
||||||
'is_public', 'return_req_id', 'paginate']
|
|
||||||
|
|
||||||
filters = {}
|
|
||||||
properties = {}
|
|
||||||
for key, value in iter(kwargs.items()):
|
|
||||||
if key in v1_keywords:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
filters[key] = value
|
|
||||||
del kwargs[key]
|
|
||||||
|
|
||||||
if properties:
|
|
||||||
filters['properties'] = properties
|
|
||||||
if filters:
|
|
||||||
kwargs['filters'] = filters
|
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def image_delete(request, image_id):
|
def image_delete(request, image_id):
|
||||||
@ -399,12 +330,6 @@ def image_list_detailed(request, marker=None, sort_dir='desc',
|
|||||||
def image_update(request, image_id, **kwargs):
|
def image_update(request, image_id, **kwargs):
|
||||||
image_data = kwargs.get('data', None)
|
image_data = kwargs.get('data', None)
|
||||||
try:
|
try:
|
||||||
# Horizon doesn't support purging image properties. Make sure we don't
|
|
||||||
# unintentionally remove properties when using v1. We don't need a
|
|
||||||
# similar setting for v2 because you have to specify which properties
|
|
||||||
# to remove, and the default is nothing gets removed.
|
|
||||||
if VERSIONS.active < 2:
|
|
||||||
kwargs['purge_props'] = False
|
|
||||||
return Image(glanceclient(request).images.update(
|
return Image(glanceclient(request).images.update(
|
||||||
image_id, **kwargs))
|
image_id, **kwargs))
|
||||||
finally:
|
finally:
|
||||||
@ -433,10 +358,7 @@ class ExternallyUploadedImage(Image):
|
|||||||
def __init__(self, apiresource, request):
|
def __init__(self, apiresource, request):
|
||||||
super(ExternallyUploadedImage, self).__init__(apiresource)
|
super(ExternallyUploadedImage, self).__init__(apiresource)
|
||||||
image_endpoint = base.url_for(request, 'image', 'publicURL')
|
image_endpoint = base.url_for(request, 'image', 'publicURL')
|
||||||
if VERSIONS.active >= 2:
|
|
||||||
upload_template = "%s/v2/images/%s/file"
|
upload_template = "%s/v2/images/%s/file"
|
||||||
else:
|
|
||||||
upload_template = "%s/v1/images/%s"
|
|
||||||
self._url = upload_template % (image_endpoint, self.id)
|
self._url = upload_template % (image_endpoint, self.id)
|
||||||
self._token_id = request.user.token.id
|
self._token_id = request.user.token.id
|
||||||
|
|
||||||
@ -509,10 +431,6 @@ def create_image_metadata(data):
|
|||||||
raise KeyError('invalid visibility option: %s' % data['visibility'])
|
raise KeyError('invalid visibility option: %s' % data['visibility'])
|
||||||
_normalize_is_public_filter(data)
|
_normalize_is_public_filter(data)
|
||||||
|
|
||||||
if VERSIONS.active < 2:
|
|
||||||
meta['properties'] = properties
|
|
||||||
meta['is_public'] = data.get('is_public', False)
|
|
||||||
else:
|
|
||||||
meta['visibility'] = data.get('visibility', 'private')
|
meta['visibility'] = data.get('visibility', 'private')
|
||||||
meta.update(properties)
|
meta.update(properties)
|
||||||
|
|
||||||
@ -548,8 +466,6 @@ def image_create(request, **kwargs):
|
|||||||
some time and is handed off to a separate thread.
|
some time and is handed off to a separate thread.
|
||||||
"""
|
"""
|
||||||
data = kwargs.pop('data', None)
|
data = kwargs.pop('data', None)
|
||||||
location = None
|
|
||||||
if VERSIONS.active >= 2:
|
|
||||||
location = kwargs.pop('location', None)
|
location = kwargs.pop('location', None)
|
||||||
|
|
||||||
image = glanceclient(request).images.create(**kwargs)
|
image = glanceclient(request).images.create(**kwargs)
|
||||||
@ -573,11 +489,7 @@ def image_create(request, **kwargs):
|
|||||||
data = SimpleUploadedFile(data.name,
|
data = SimpleUploadedFile(data.name,
|
||||||
data.read(),
|
data.read(),
|
||||||
data.content_type)
|
data.content_type)
|
||||||
if VERSIONS.active < 2:
|
|
||||||
thread.start_new_thread(image_update,
|
|
||||||
(request, image.id),
|
|
||||||
{'data': data})
|
|
||||||
else:
|
|
||||||
def upload():
|
def upload():
|
||||||
try:
|
try:
|
||||||
return glanceclient(request).images.upload(image.id, data)
|
return glanceclient(request).images.upload(image.id, data)
|
||||||
@ -597,7 +509,7 @@ def image_create(request, **kwargs):
|
|||||||
@profiler.trace
|
@profiler.trace
|
||||||
def image_update_properties(request, image_id, remove_props=None, **kwargs):
|
def image_update_properties(request, image_id, remove_props=None, **kwargs):
|
||||||
"""Add or update a custom property of an image."""
|
"""Add or update a custom property of an image."""
|
||||||
return glanceclient(request, '2').images.update(image_id,
|
return glanceclient(request).images.update(image_id,
|
||||||
remove_props,
|
remove_props,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
@ -666,7 +578,7 @@ def filter_properties_target(namespaces_iter,
|
|||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def metadefs_namespace_get(request, namespace, resource_type=None, wrap=False):
|
def metadefs_namespace_get(request, namespace, resource_type=None, wrap=False):
|
||||||
namespace = glanceclient(request, '2').\
|
namespace = glanceclient(request).\
|
||||||
metadefs_namespace.get(namespace, resource_type=resource_type)
|
metadefs_namespace.get(namespace, resource_type=resource_type)
|
||||||
# There were problems with using the wrapper class in
|
# There were problems with using the wrapper class in
|
||||||
# nested json serialization. So sometimes, it is not desirable
|
# nested json serialization. So sometimes, it is not desirable
|
||||||
@ -709,9 +621,6 @@ def metadefs_namespace_list(request,
|
|||||||
"""
|
"""
|
||||||
# Listing namespaces requires the v2 API. If not supported we return an
|
# Listing namespaces requires the v2 API. If not supported we return an
|
||||||
# empty array so callers don't need to worry about version checking.
|
# empty array so callers don't need to worry about version checking.
|
||||||
if get_version() < 2:
|
|
||||||
return [], False, False
|
|
||||||
|
|
||||||
if filters is None:
|
if filters is None:
|
||||||
filters = {}
|
filters = {}
|
||||||
limit = settings.API_RESULT_LIMIT
|
limit = settings.API_RESULT_LIMIT
|
||||||
@ -728,7 +637,7 @@ def metadefs_namespace_list(request,
|
|||||||
kwargs['sort_dir'] = sort_dir
|
kwargs['sort_dir'] = sort_dir
|
||||||
kwargs['sort_key'] = sort_key
|
kwargs['sort_key'] = sort_key
|
||||||
|
|
||||||
namespaces_iter = glanceclient(request, '2').metadefs_namespace.list(
|
namespaces_iter = glanceclient(request).metadefs_namespace.list(
|
||||||
page_size=request_size, limit=limit, **kwargs)
|
page_size=request_size, limit=limit, **kwargs)
|
||||||
|
|
||||||
# Filter the namespaces based on the provided properties_target since this
|
# Filter the namespaces based on the provided properties_target since this
|
||||||
@ -780,34 +689,31 @@ def metadefs_namespace_full_list(request, resource_type, filters=None,
|
|||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def metadefs_namespace_create(request, namespace):
|
def metadefs_namespace_create(request, namespace):
|
||||||
return glanceclient(request, '2').metadefs_namespace.create(**namespace)
|
return glanceclient(request).metadefs_namespace.create(**namespace)
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def metadefs_namespace_update(request, namespace_name, **properties):
|
def metadefs_namespace_update(request, namespace_name, **properties):
|
||||||
return glanceclient(request, '2').metadefs_namespace.update(
|
return glanceclient(request).metadefs_namespace.update(
|
||||||
namespace_name,
|
namespace_name,
|
||||||
**properties)
|
**properties)
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def metadefs_namespace_delete(request, namespace_name):
|
def metadefs_namespace_delete(request, namespace_name):
|
||||||
return glanceclient(request, '2').metadefs_namespace.delete(namespace_name)
|
return glanceclient(request).metadefs_namespace.delete(namespace_name)
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def metadefs_resource_types_list(request):
|
def metadefs_resource_types_list(request):
|
||||||
# Listing Resource Types requires the v2 API. If not supported we return
|
# Listing Resource Types requires the v2 API. If not supported we return
|
||||||
# an empty array so callers don't need to worry about version checking.
|
# an empty array so callers don't need to worry about version checking.
|
||||||
if get_version() < 2:
|
return glanceclient(request).metadefs_resource_type.list()
|
||||||
return []
|
|
||||||
else:
|
|
||||||
return glanceclient(request, '2').metadefs_resource_type.list()
|
|
||||||
|
|
||||||
|
|
||||||
@profiler.trace
|
@profiler.trace
|
||||||
def metadefs_namespace_resource_types(request, namespace_name):
|
def metadefs_namespace_resource_types(request, namespace_name):
|
||||||
resource_types = glanceclient(request, '2').metadefs_resource_type.get(
|
resource_types = glanceclient(request).metadefs_resource_type.get(
|
||||||
namespace_name)
|
namespace_name)
|
||||||
|
|
||||||
# metadefs_resource_type.get() returns generator, converting it to list
|
# metadefs_resource_type.get() returns generator, converting it to list
|
||||||
@ -818,7 +724,7 @@ def metadefs_namespace_resource_types(request, namespace_name):
|
|||||||
def metadefs_namespace_add_resource_type(request,
|
def metadefs_namespace_add_resource_type(request,
|
||||||
namespace_name,
|
namespace_name,
|
||||||
resource_type):
|
resource_type):
|
||||||
return glanceclient(request, '2').metadefs_resource_type.associate(
|
return glanceclient(request).metadefs_resource_type.associate(
|
||||||
namespace_name, **resource_type)
|
namespace_name, **resource_type)
|
||||||
|
|
||||||
|
|
||||||
@ -826,7 +732,7 @@ def metadefs_namespace_add_resource_type(request,
|
|||||||
def metadefs_namespace_remove_resource_type(request,
|
def metadefs_namespace_remove_resource_type(request,
|
||||||
namespace_name,
|
namespace_name,
|
||||||
resource_type_name):
|
resource_type_name):
|
||||||
glanceclient(request, '2').metadefs_resource_type.deassociate(
|
glanceclient(request).metadefs_resource_type.deassociate(
|
||||||
namespace_name, resource_type_name)
|
namespace_name, resource_type_name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,52 +87,6 @@ class UpdateImageFormTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
image.id)
|
image.id)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
@mock.patch.object(api.glance, 'image_get')
|
|
||||||
@mock.patch.object(api.glance, 'image_update')
|
|
||||||
def test_image_update_post_v1(self, mock_image_update, mock_image_get):
|
|
||||||
image = self.images.first()
|
|
||||||
data = {
|
|
||||||
'name': u'Ubuntu 11.10',
|
|
||||||
'image_id': str(image.id),
|
|
||||||
'description': u'Login with admin/admin',
|
|
||||||
'source_type': u'url',
|
|
||||||
'image_url': u'http://cloud-images.ubuntu.com/releases/'
|
|
||||||
u'oneiric/release/ubuntu-11.10-server-cloudimg'
|
|
||||||
u'-amd64-disk1.img',
|
|
||||||
'disk_format': u'qcow2',
|
|
||||||
'architecture': u'x86-64',
|
|
||||||
'min_disk': 15,
|
|
||||||
'min_ram': 512,
|
|
||||||
'is_public': False,
|
|
||||||
'protected': False,
|
|
||||||
'method': 'UpdateImageForm'}
|
|
||||||
|
|
||||||
mock_image_get.return_value = image
|
|
||||||
mock_image_update.return_value = image
|
|
||||||
|
|
||||||
url = reverse('horizon:project:images:images:update',
|
|
||||||
args=[image.id])
|
|
||||||
res = self.client.post(url, data)
|
|
||||||
|
|
||||||
self.assertNoFormErrors(res)
|
|
||||||
self.assertEqual(res.status_code, 302)
|
|
||||||
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
|
||||||
str(image.id))
|
|
||||||
mock_image_update.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(),
|
|
||||||
image.id,
|
|
||||||
is_public=data['is_public'],
|
|
||||||
protected=data['protected'],
|
|
||||||
disk_format=data['disk_format'],
|
|
||||||
container_format="bare",
|
|
||||||
name=data['name'],
|
|
||||||
min_ram=data['min_ram'],
|
|
||||||
min_disk=data['min_disk'],
|
|
||||||
properties={
|
|
||||||
'description': data['description'],
|
|
||||||
'architecture': data['architecture']})
|
|
||||||
|
|
||||||
@mock.patch.object(api.glance, 'image_get')
|
@mock.patch.object(api.glance, 'image_get')
|
||||||
@mock.patch.object(api.glance, 'image_update')
|
@mock.patch.object(api.glance, 'image_update')
|
||||||
def test_image_update_post_v2(self, mock_image_update, mock_image_get):
|
def test_image_update_post_v2(self, mock_image_update, mock_image_get):
|
||||||
@ -196,30 +150,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertTemplateUsed(res, 'project/images/images/create.html')
|
self.assertTemplateUsed(res, 'project/images/images/create.html')
|
||||||
mock_image_list.assert_has_calls(image_calls)
|
mock_image_list.assert_has_calls(image_calls)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_create_post_copy_from_v1(self):
|
|
||||||
data = {
|
|
||||||
'source_type': u'url',
|
|
||||||
'image_url': u'http://cloud-images.ubuntu.com/releases/'
|
|
||||||
u'oneiric/release/ubuntu-11.10-server-cloudimg'
|
|
||||||
u'-amd64-disk1.img',
|
|
||||||
'is_copying': True}
|
|
||||||
|
|
||||||
api_data = {'copy_from': data['image_url']}
|
|
||||||
self._test_image_create(data, api_data)
|
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_create_post_location_v1(self):
|
|
||||||
data = {
|
|
||||||
'source_type': u'url',
|
|
||||||
'image_url': u'http://cloud-images.ubuntu.com/releases/'
|
|
||||||
u'oneiric/release/ubuntu-11.10-server-cloudimg'
|
|
||||||
u'-amd64-disk1.img',
|
|
||||||
'is_copying': False}
|
|
||||||
|
|
||||||
api_data = {'location': data['image_url']}
|
|
||||||
self._test_image_create(data, api_data)
|
|
||||||
|
|
||||||
@override_settings(IMAGES_ALLOW_LOCATION=True)
|
@override_settings(IMAGES_ALLOW_LOCATION=True)
|
||||||
def test_image_create_post_location_v2(self):
|
def test_image_create_post_location_v2(self):
|
||||||
data = {
|
data = {
|
||||||
@ -231,19 +161,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
api_data = {'location': data['image_url']}
|
api_data = {'location': data['image_url']}
|
||||||
self._test_image_create(data, api_data)
|
self._test_image_create(data, api_data)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_create_post_upload_v1(self):
|
|
||||||
temp_file = tempfile.NamedTemporaryFile()
|
|
||||||
temp_file.write(b'123')
|
|
||||||
temp_file.flush()
|
|
||||||
temp_file.seek(0)
|
|
||||||
|
|
||||||
data = {'source_type': u'file',
|
|
||||||
'image_file': temp_file}
|
|
||||||
|
|
||||||
api_data = {'data': test.IsA(InMemoryUploadedFile)}
|
|
||||||
self._test_image_create(data, api_data)
|
|
||||||
|
|
||||||
def test_image_create_post_upload_v2(self):
|
def test_image_create_post_upload_v2(self):
|
||||||
temp_file = tempfile.NamedTemporaryFile()
|
temp_file = tempfile.NamedTemporaryFile()
|
||||||
temp_file.write(b'123')
|
temp_file.write(b'123')
|
||||||
@ -256,23 +173,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
api_data = {'data': test.IsA(InMemoryUploadedFile)}
|
api_data = {'data': test.IsA(InMemoryUploadedFile)}
|
||||||
self._test_image_create(data, api_data)
|
self._test_image_create(data, api_data)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_create_post_with_kernel_ramdisk_v1(self):
|
|
||||||
temp_file = tempfile.NamedTemporaryFile()
|
|
||||||
temp_file.write(b'123')
|
|
||||||
temp_file.flush()
|
|
||||||
temp_file.seek(0)
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'source_type': u'file',
|
|
||||||
'image_file': temp_file,
|
|
||||||
'kernel_id': '007e7d55-fe1e-4c5c-bf08-44b4a496482e',
|
|
||||||
'ramdisk_id': '007e7d55-fe1e-4c5c-bf08-44b4a496482a'
|
|
||||||
}
|
|
||||||
|
|
||||||
api_data = {'data': test.IsA(InMemoryUploadedFile)}
|
|
||||||
self._test_image_create(data, api_data)
|
|
||||||
|
|
||||||
def test_image_create_post_with_kernel_ramdisk_v2(self):
|
def test_image_create_post_with_kernel_ramdisk_v2(self):
|
||||||
temp_file = tempfile.NamedTemporaryFile()
|
temp_file = tempfile.NamedTemporaryFile()
|
||||||
temp_file.write(b'123')
|
temp_file.write(b'123')
|
||||||
@ -360,12 +260,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
six.text_type(image.id))
|
six.text_type(image.id))
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_detail_get_v1(self):
|
|
||||||
image = self.images.first()
|
|
||||||
|
|
||||||
self._test_image_detail_get(image)
|
|
||||||
|
|
||||||
def test_image_detail_get_v2(self):
|
def test_image_detail_get_v2(self):
|
||||||
image = self.imagesV2.first()
|
image = self.imagesV2.first()
|
||||||
|
|
||||||
@ -397,12 +291,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
six.text_type(image.id))
|
six.text_type(image.id))
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_image_detail_custom_props_get_v1(self):
|
|
||||||
image = self.images.list()[9]
|
|
||||||
|
|
||||||
self._test_image_detail_custom_props_get(image)
|
|
||||||
|
|
||||||
def test_image_detail_custom_props_get_v2(self):
|
def test_image_detail_custom_props_get_v2(self):
|
||||||
image = self.imagesV2.list()[2]
|
image = self.imagesV2.list()[2]
|
||||||
|
|
||||||
@ -422,12 +310,6 @@ class ImageViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
mock_image_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
six.text_type(image.id))
|
six.text_type(image.id))
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_protected_image_detail_get_v1(self):
|
|
||||||
image = self.images.list()[2]
|
|
||||||
|
|
||||||
self._test_protected_image_detail_get(image)
|
|
||||||
|
|
||||||
def test_protected_image_detail_get_v2(self):
|
def test_protected_image_detail_get_v2(self):
|
||||||
image = self.imagesV2.list()[1]
|
image = self.imagesV2.list()[1]
|
||||||
|
|
||||||
|
@ -885,13 +885,6 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
image.min_disk = 30
|
image.min_disk = 30
|
||||||
self._test_create_volume_from_image_under_image_min_disk_size(image)
|
self._test_create_volume_from_image_under_image_min_disk_size(image)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_create_volume_from_image_under_image_prop_min_disk_size_v1(self):
|
|
||||||
image = self.images.get(name="protected_images")
|
|
||||||
image.min_disk = 0
|
|
||||||
image.properties['min_disk'] = 30
|
|
||||||
self._test_create_volume_from_image_under_image_min_disk_size(image)
|
|
||||||
|
|
||||||
def test_create_volume_from_image_under_image_prop_min_disk_size_v2(self):
|
def test_create_volume_from_image_under_image_prop_min_disk_size_v2(self):
|
||||||
image = self.imagesV2.get(name="protected_images")
|
image = self.imagesV2.get(name="protected_images")
|
||||||
self._test_create_volume_from_image_under_image_min_disk_size(image)
|
self._test_create_volume_from_image_under_image_min_disk_size(image)
|
||||||
|
@ -12,8 +12,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from glanceclient.v1 import images
|
|
||||||
|
|
||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
from openstack_dashboard.test.test_data import utils
|
from openstack_dashboard.test.test_data import utils
|
||||||
|
|
||||||
@ -47,6 +45,9 @@ class APIResourceV2(dict):
|
|||||||
|
|
||||||
|
|
||||||
def data(TEST):
|
def data(TEST):
|
||||||
|
# TODO(e0ne): merge images with imagesV2 and snapshots with snapshotsV2
|
||||||
|
# test data.
|
||||||
|
|
||||||
TEST.images = utils.TestDataContainer()
|
TEST.images = utils.TestDataContainer()
|
||||||
TEST.images_api = utils.TestDataContainer()
|
TEST.images_api = utils.TestDataContainer()
|
||||||
TEST.snapshots = utils.TestDataContainer()
|
TEST.snapshots = utils.TestDataContainer()
|
||||||
@ -90,14 +91,13 @@ def data(TEST):
|
|||||||
'is_public': False,
|
'is_public': False,
|
||||||
'protected': False}
|
'protected': False}
|
||||||
|
|
||||||
snapshot = images.Image(images.ImageManager(None), snapshot_dict)
|
snapshot = APIResourceV2(snapshot_dict)
|
||||||
TEST.snapshots.add(api.glance.Image(snapshot))
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
snapshot = images.Image(images.ImageManager(None), snapshot_dict_no_owner)
|
snapshot = APIResourceV2(snapshot_dict_no_owner)
|
||||||
TEST.snapshots.add(api.glance.Image(snapshot))
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
snapshot = images.Image(images.ImageManager(None), snapshot_dict_queued)
|
snapshot = APIResourceV2(snapshot_dict_queued)
|
||||||
TEST.snapshots.add(api.glance.Image(snapshot))
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
snapshot = images.Image(images.ImageManager(None),
|
snapshot = APIResourceV2(snapshot_dict_with_volume)
|
||||||
snapshot_dict_with_volume)
|
|
||||||
TEST.snapshots.add(api.glance.Image(snapshot))
|
TEST.snapshots.add(api.glance.Image(snapshot))
|
||||||
|
|
||||||
# Images
|
# Images
|
||||||
@ -115,7 +115,7 @@ def data(TEST):
|
|||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0,
|
'min_ram': 0,
|
||||||
'created_at': '2014-02-14T20:56:53'}
|
'created_at': '2014-02-14T20:56:53'}
|
||||||
public_image = images.Image(images.ImageManager(None), image_dict)
|
public_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': 'a001c047-22f8-47d0-80a1-8ec94a9524fe',
|
image_dict = {'id': 'a001c047-22f8-47d0-80a1-8ec94a9524fe',
|
||||||
'name': 'private_image',
|
'name': 'private_image',
|
||||||
@ -129,7 +129,7 @@ def data(TEST):
|
|||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0,
|
'min_ram': 0,
|
||||||
'created_at': '2014-03-14T12:56:53'}
|
'created_at': '2014-03-14T12:56:53'}
|
||||||
private_image = images.Image(images.ImageManager(None), image_dict)
|
private_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': 'd6936c86-7fec-474a-85c5-5e467b371c3c',
|
image_dict = {'id': 'd6936c86-7fec-474a-85c5-5e467b371c3c',
|
||||||
'name': 'protected_images',
|
'name': 'protected_images',
|
||||||
@ -144,7 +144,7 @@ def data(TEST):
|
|||||||
'protected': True,
|
'protected': True,
|
||||||
'min_ram': 0,
|
'min_ram': 0,
|
||||||
'created_at': '2014-03-16T06:22:14'}
|
'created_at': '2014-03-16T06:22:14'}
|
||||||
protected_image = images.Image(images.ImageManager(None), image_dict)
|
protected_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': '278905a6-4b52-4d1e-98f9-8c57bb25ba32',
|
image_dict = {'id': '278905a6-4b52-4d1e-98f9-8c57bb25ba32',
|
||||||
'name': None,
|
'name': None,
|
||||||
@ -158,7 +158,7 @@ def data(TEST):
|
|||||||
'is_public': True,
|
'is_public': True,
|
||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0}
|
'min_ram': 0}
|
||||||
public_image2 = images.Image(images.ImageManager(None), image_dict)
|
public_image2 = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': '710a1acf-a3e3-41dd-a32d-5d6b6c86ea10',
|
image_dict = {'id': '710a1acf-a3e3-41dd-a32d-5d6b6c86ea10',
|
||||||
'name': 'private_image 2',
|
'name': 'private_image 2',
|
||||||
@ -171,7 +171,7 @@ def data(TEST):
|
|||||||
'is_public': False,
|
'is_public': False,
|
||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0}
|
'min_ram': 0}
|
||||||
private_image2 = images.Image(images.ImageManager(None), image_dict)
|
private_image2 = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': '7cd892fd-5652-40f3-a450-547615680132',
|
image_dict = {'id': '7cd892fd-5652-40f3-a450-547615680132',
|
||||||
'name': 'private_image 3',
|
'name': 'private_image 3',
|
||||||
@ -184,7 +184,7 @@ def data(TEST):
|
|||||||
'is_public': False,
|
'is_public': False,
|
||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0}
|
'min_ram': 0}
|
||||||
private_image3 = images.Image(images.ImageManager(None), image_dict)
|
private_image3 = APIResourceV2(image_dict)
|
||||||
|
|
||||||
# A community image. Not public and not local tenant, but visibility
|
# A community image. Not public and not local tenant, but visibility
|
||||||
# is set as 'community'
|
# is set as 'community'
|
||||||
@ -200,7 +200,7 @@ def data(TEST):
|
|||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0,
|
'min_ram': 0,
|
||||||
'visibility': 'community'}
|
'visibility': 'community'}
|
||||||
community_image = images.Image(images.ImageManager(None), image_dict)
|
community_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
# A shared image. Not public and not local tenant.
|
# A shared image. Not public and not local tenant.
|
||||||
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
||||||
@ -214,7 +214,7 @@ def data(TEST):
|
|||||||
'is_public': False,
|
'is_public': False,
|
||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0}
|
'min_ram': 0}
|
||||||
shared_image1 = images.Image(images.ImageManager(None), image_dict)
|
shared_image1 = APIResourceV2(image_dict)
|
||||||
|
|
||||||
# "Official" image. Public and tenant matches an entry
|
# "Official" image. Public and tenant matches an entry
|
||||||
# in IMAGES_LIST_FILTER_TENANTS.
|
# in IMAGES_LIST_FILTER_TENANTS.
|
||||||
@ -229,7 +229,7 @@ def data(TEST):
|
|||||||
'is_public': True,
|
'is_public': True,
|
||||||
'protected': False,
|
'protected': False,
|
||||||
'min_ram': 0}
|
'min_ram': 0}
|
||||||
official_image1 = images.Image(images.ImageManager(None), image_dict)
|
official_image1 = APIResourceV2(image_dict)
|
||||||
|
|
||||||
image_dict = {'id': 'a67e7d45-fe1e-4c5c-bf08-44b4a4964822',
|
image_dict = {'id': 'a67e7d45-fe1e-4c5c-bf08-44b4a4964822',
|
||||||
'name': 'multi_prop_image',
|
'name': 'multi_prop_image',
|
||||||
@ -244,7 +244,7 @@ def data(TEST):
|
|||||||
'bar': u'bar val'},
|
'bar': u'bar val'},
|
||||||
'is_public': True,
|
'is_public': True,
|
||||||
'protected': False}
|
'protected': False}
|
||||||
multi_prop_image = images.Image(images.ImageManager(None), image_dict)
|
multi_prop_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
# An image without name being returned based on current api
|
# An image without name being returned based on current api
|
||||||
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
image_dict = {'id': 'c8756975-7a3b-4e43-b7f7-433576112849',
|
||||||
@ -256,7 +256,7 @@ def data(TEST):
|
|||||||
'container_format': 'aki',
|
'container_format': 'aki',
|
||||||
'is_public': False,
|
'is_public': False,
|
||||||
'protected': False}
|
'protected': False}
|
||||||
no_name_image = images.Image(images.ImageManager(None), image_dict)
|
no_name_image = APIResourceV2(image_dict)
|
||||||
|
|
||||||
TEST.images_api.add(public_image, private_image, protected_image,
|
TEST.images_api.add(public_image, private_image, protected_image,
|
||||||
public_image2, private_image2, private_image3,
|
public_image2, private_image2, private_image3,
|
||||||
|
@ -77,38 +77,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
glance.Image().delete(request, "1")
|
glance.Image().delete(request, "1")
|
||||||
self.mock_image_delete.assert_called_once_with(request, "1")
|
self.mock_image_delete.assert_called_once_with(request, "1")
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_update', 'VERSIONS']})
|
|
||||||
def test_image_edit_v1(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "aki", "container_format": "aki",
|
|
||||||
"visibility": "public", "protected": false,
|
|
||||||
"image_url": "test.com",
|
|
||||||
"source_type": "url", "architecture": "testArch",
|
|
||||||
"description": "description", "kernel": "kernel",
|
|
||||||
"min_disk": 10, "min_ram": 5, "ramdisk": 10 }
|
|
||||||
''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
self.mock_image_update.return_value = self.images.first()
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'aki',
|
|
||||||
'container_format': 'aki',
|
|
||||||
'is_public': True,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 10,
|
|
||||||
'min_ram': 5,
|
|
||||||
'properties': {'description': 'description',
|
|
||||||
'architecture': 'testArch',
|
|
||||||
'ramdisk_id': 10,
|
|
||||||
'kernel_id': 'kernel'}
|
|
||||||
}
|
|
||||||
|
|
||||||
response = glance.Image().patch(request, "1")
|
|
||||||
self.assertStatusCode(response, 204)
|
|
||||||
self.assertEqual(response.content.decode('utf-8'), '')
|
|
||||||
self.mock_image_update.assert_called_once_with(request, '1',
|
|
||||||
**metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_update', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_update', 'VERSIONS']})
|
||||||
def test_image_edit_v2(self):
|
def test_image_edit_v2(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -166,43 +134,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
filters=filters,
|
filters=filters,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
|
||||||
def test_image_create_v1_basic(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "aki", "import_data": false,
|
|
||||||
"visibility": "public", "container_format": "aki",
|
|
||||||
"protected": false, "image_url": "test.com",
|
|
||||||
"source_type": "url", "architecture": "testArch",
|
|
||||||
"description": "description", "kernel": "kernel",
|
|
||||||
"min_disk": 10, "min_ram": 5, "ramdisk": 10 }
|
|
||||||
''')
|
|
||||||
new = self.mock_image_create.return_value
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
new.to_dict.return_value = {'name': 'testimage'}
|
|
||||||
new.name = 'testimage'
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'aki',
|
|
||||||
'container_format': 'aki',
|
|
||||||
'is_public': True,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 10,
|
|
||||||
'min_ram': 5,
|
|
||||||
'location': 'test.com',
|
|
||||||
'properties': {
|
|
||||||
'description': 'description',
|
|
||||||
'architecture': 'testArch',
|
|
||||||
'ramdisk_id': 10,
|
|
||||||
'kernel_id': 'kernel',
|
|
||||||
}}
|
|
||||||
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 201)
|
|
||||||
self.assertEqual(response.content.decode('utf-8'),
|
|
||||||
'{"name": "testimage"}')
|
|
||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
||||||
def test_image_create_v2_basic(self):
|
def test_image_create_v2_basic(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -239,43 +170,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
self.mock_image_create.assert_called_once_with(request, **metadata)
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
|
||||||
def test_image_create_v1_shared(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "aki", "import_data": false,
|
|
||||||
"visibility": "shared", "container_format": "aki",
|
|
||||||
"protected": false, "image_url": "test.com",
|
|
||||||
"source_type": "url", "architecture": "testArch",
|
|
||||||
"description": "description", "kernel": "kernel",
|
|
||||||
"min_disk": 10, "min_ram": 5, "ramdisk": 10 }
|
|
||||||
''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
new = self.mock_image_create.return_value
|
|
||||||
new.to_dict.return_value = {'name': 'testimage'}
|
|
||||||
new.name = 'testimage'
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'aki',
|
|
||||||
'container_format': 'aki',
|
|
||||||
'is_public': False,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 10,
|
|
||||||
'min_ram': 5,
|
|
||||||
'location': 'test.com',
|
|
||||||
'properties': {
|
|
||||||
'description': 'description',
|
|
||||||
'architecture': 'testArch',
|
|
||||||
'ramdisk_id': 10,
|
|
||||||
'kernel_id': 'kernel',
|
|
||||||
}}
|
|
||||||
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 201)
|
|
||||||
self.assertEqual(response.content.decode('utf-8'),
|
|
||||||
'{"name": "testimage"}')
|
|
||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
||||||
def test_image_create_v2_shared(self):
|
def test_image_create_v2_shared(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -312,43 +206,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
self.mock_image_create.assert_called_once_with(request, **metadata)
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
|
||||||
def test_image_create_v1_private(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "aki", "import_data": false,
|
|
||||||
"visibility": "private", "container_format": "aki",
|
|
||||||
"protected": false, "image_url": "test.com",
|
|
||||||
"source_type": "url", "architecture": "testArch",
|
|
||||||
"description": "description", "kernel": "kernel",
|
|
||||||
"min_disk": 10, "min_ram": 5, "ramdisk": 10 }
|
|
||||||
''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
new = self.mock_image_create.return_value
|
|
||||||
new.to_dict.return_value = {'name': 'testimage'}
|
|
||||||
new.name = 'testimage'
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'aki',
|
|
||||||
'container_format': 'aki',
|
|
||||||
'is_public': False,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 10,
|
|
||||||
'min_ram': 5,
|
|
||||||
'location': 'test.com',
|
|
||||||
'properties': {
|
|
||||||
'description': 'description',
|
|
||||||
'architecture': 'testArch',
|
|
||||||
'ramdisk_id': 10,
|
|
||||||
'kernel_id': 'kernel',
|
|
||||||
}}
|
|
||||||
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 201)
|
|
||||||
self.assertEqual(response.content.decode('utf-8'),
|
|
||||||
'{"name": "testimage"}')
|
|
||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
||||||
def test_image_create_v2_private(self):
|
def test_image_create_v2_private(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -385,23 +242,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
self.mock_image_create.assert_called_once_with(request, **metadata)
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['VERSIONS']})
|
|
||||||
def test_image_create_v1_bad_visibility(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "aki", "import_data": false,
|
|
||||||
"visibility": "verybad", "container_format": "aki",
|
|
||||||
"protected": false, "image_url": "test.com",
|
|
||||||
"source_type": "url", "architecture": "testArch",
|
|
||||||
"description": "description", "kernel": "kernel",
|
|
||||||
"min_disk": 10, "min_ram": 5, "ramdisk": 10 }
|
|
||||||
''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 400)
|
|
||||||
self.assertEqual(response.content.decode('utf-8'),
|
|
||||||
'"invalid visibility option: verybad"')
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['VERSIONS']})
|
@test.create_mocks({api.glance: ['VERSIONS']})
|
||||||
def test_image_create_v2_bad_visibility(self):
|
def test_image_create_v2_bad_visibility(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -419,33 +259,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertEqual(response.content.decode('utf-8'),
|
self.assertEqual(response.content.decode('utf-8'),
|
||||||
'"invalid visibility option: verybad"')
|
'"invalid visibility option: verybad"')
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
|
||||||
def test_image_create_v1_required(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "raw", "import_data": true,
|
|
||||||
"container_format": "docker",
|
|
||||||
"visibility": "public", "protected": false,
|
|
||||||
"source_type": "url", "image_url": "test.com" }''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
new = self.mock_image_create.return_value
|
|
||||||
new.to_dict.return_value = {'name': 'testimage'}
|
|
||||||
new.name = 'testimage'
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'raw',
|
|
||||||
'container_format': 'docker',
|
|
||||||
'copy_from': 'test.com',
|
|
||||||
'is_public': True,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 0,
|
|
||||||
'min_ram': 0,
|
|
||||||
'properties': {}
|
|
||||||
}
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 201)
|
|
||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
||||||
def test_image_create_v2_required(self):
|
def test_image_create_v2_required(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
@ -472,34 +285,6 @@ class ImagesRestTestCase(test.ResetImageAPIVersionMixin, test.TestCase):
|
|||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
self.mock_image_create.assert_called_once_with(request, **metadata)
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
|
||||||
def test_image_create_v1_additional_props(self):
|
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
|
||||||
"disk_format": "raw", "import_data": true,
|
|
||||||
"container_format": "docker",
|
|
||||||
"visibility": "public", "protected": false,
|
|
||||||
"arbitrary": "property", "another": "prop",
|
|
||||||
"source_type": "url", "image_url": "test.com" }''')
|
|
||||||
self.mock_VERSIONS.active = 1
|
|
||||||
new = self.mock_image_create.return_value
|
|
||||||
new.to_dict.return_value = {'name': 'testimage'}
|
|
||||||
new.name = 'testimage'
|
|
||||||
|
|
||||||
metadata = {'name': 'Test',
|
|
||||||
'disk_format': 'raw',
|
|
||||||
'container_format': 'docker',
|
|
||||||
'copy_from': 'test.com',
|
|
||||||
'is_public': True,
|
|
||||||
'protected': False,
|
|
||||||
'min_disk': 0,
|
|
||||||
'min_ram': 0,
|
|
||||||
'properties': {'arbitrary': 'property', 'another': 'prop'}
|
|
||||||
}
|
|
||||||
response = glance.Images().put(request)
|
|
||||||
self.assertStatusCode(response, 201)
|
|
||||||
self.assertEqual(response['location'], '/api/glance/images/testimage')
|
|
||||||
self.mock_image_create.assert_called_once_with(request, **metadata)
|
|
||||||
|
|
||||||
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
@test.create_mocks({api.glance: ['image_create', 'VERSIONS']})
|
||||||
def test_image_create_v2_additional_props(self):
|
def test_image_create_v2_additional_props(self):
|
||||||
request = self.mock_rest_request(body='''{"name": "Test",
|
request = self.mock_rest_request(body='''{"name": "Test",
|
||||||
|
@ -359,18 +359,6 @@ class GlanceApiTests(test.APIMockTestCase):
|
|||||||
self.assertEqual(1, len(defs))
|
self.assertEqual(1, len(defs))
|
||||||
self.assertEqual('namespace_4', defs[0].namespace)
|
self.assertEqual('namespace_4', defs[0].namespace)
|
||||||
|
|
||||||
@mock.patch.object(api.glance, 'get_version', return_value=1)
|
|
||||||
def test_metadefs_namespace_list_v1(self, mock_version):
|
|
||||||
defs, more, prev = api.glance.metadefs_namespace_list(self.request)
|
|
||||||
self.assertItemsEqual(defs, [])
|
|
||||||
self.assertFalse(more)
|
|
||||||
self.assertFalse(prev)
|
|
||||||
|
|
||||||
@mock.patch.object(api.glance, 'get_version', return_value=1)
|
|
||||||
def test_metadefs_resource_types_list_v1(self, mock_version):
|
|
||||||
res_types = api.glance.metadefs_resource_types_list(self.request)
|
|
||||||
self.assertItemsEqual(res_types, [])
|
|
||||||
|
|
||||||
@mock.patch.object(api.glance, 'glanceclient')
|
@mock.patch.object(api.glance, 'glanceclient')
|
||||||
def _test_image_create_external_upload(self, mock_glanceclient,
|
def _test_image_create_external_upload(self, mock_glanceclient,
|
||||||
api_version=2):
|
api_version=2):
|
||||||
@ -393,39 +381,9 @@ class GlanceApiTests(test.APIMockTestCase):
|
|||||||
self.assertEqual(upload_url, actual_image.upload_url)
|
self.assertEqual(upload_url, actual_image.upload_url)
|
||||||
self.assertEqual(self.request.user.token.id, actual_image.token_id)
|
self.assertEqual(self.request.user.token.id, actual_image.token_id)
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={"image": 1})
|
|
||||||
def test_image_create_v1_external_upload(self):
|
|
||||||
self._test_image_create_external_upload(api_version=1)
|
|
||||||
|
|
||||||
def test_image_create_v2_external_upload(self):
|
def test_image_create_v2_external_upload(self):
|
||||||
self._test_image_create_external_upload()
|
self._test_image_create_external_upload()
|
||||||
|
|
||||||
@override_settings(OPENSTACK_API_VERSIONS={'image': 1})
|
|
||||||
def test_create_image_metadata_docker_v1(self):
|
|
||||||
form_data = {
|
|
||||||
'name': u'Docker image',
|
|
||||||
'description': u'Docker image test',
|
|
||||||
'source_type': u'url',
|
|
||||||
'image_url': u'/',
|
|
||||||
'disk_format': u'docker',
|
|
||||||
'architecture': u'x86-64',
|
|
||||||
'min_disk': 15,
|
|
||||||
'min_ram': 512,
|
|
||||||
'is_public': False,
|
|
||||||
'protected': False,
|
|
||||||
'is_copying': False
|
|
||||||
}
|
|
||||||
meta = api.glance.create_image_metadata(form_data)
|
|
||||||
self.assertEqual(meta['disk_format'], 'raw')
|
|
||||||
self.assertEqual(meta['container_format'], 'docker')
|
|
||||||
self.assertIn('properties', meta)
|
|
||||||
self.assertNotIn('description', meta)
|
|
||||||
self.assertNotIn('architecture', meta)
|
|
||||||
self.assertEqual(meta['properties']['description'],
|
|
||||||
form_data['description'])
|
|
||||||
self.assertEqual(meta['properties']['architecture'],
|
|
||||||
form_data['architecture'])
|
|
||||||
|
|
||||||
def test_create_image_metadata_docker_v2(self):
|
def test_create_image_metadata_docker_v2(self):
|
||||||
form_data = {
|
form_data = {
|
||||||
'name': u'Docker image',
|
'name': u'Docker image',
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Glance API V1 support has been dropped in Ussuri release. Glance V1 API
|
||||||
|
support was deprecated in Stein release.
|
Loading…
Reference in New Issue
Block a user