Completely remove support for deprecated Glance V1
Also removes support for having several API versions for the Image API. We do not do it for Neutron and Swift. And if we ever support the (hypothetical) Glance V3 API, we better do it transparently, not with a configuration option (maybe using openstacksdk). Cleans up Glance V1 specific features like image.is_public or a separate image.properties field. The code should be consolidated into fewer modules in a follow-up. Story: #1670423 Task: #26830 Change-Id: I08a01eadbe8a2dec4c02674bed0391846632ef06
This commit is contained in:
parent
9c819cd153
commit
fe94fb13fa
@ -110,7 +110,7 @@ def check_image_service(func):
|
||||
if self.context.auth_token:
|
||||
user_auth = keystone.get_service_auth(self.context, self.endpoint,
|
||||
service_auth)
|
||||
self.client = client.Client(self.version, session=session,
|
||||
self.client = client.Client(2, session=session,
|
||||
auth=user_auth or service_auth,
|
||||
endpoint_override=self.endpoint,
|
||||
global_request_id=self.context.global_id)
|
||||
@ -121,9 +121,8 @@ def check_image_service(func):
|
||||
|
||||
class BaseImageService(object):
|
||||
|
||||
def __init__(self, client=None, version=1, context=None):
|
||||
def __init__(self, client=None, context=None):
|
||||
self.client = client
|
||||
self.version = version
|
||||
self.context = context
|
||||
self.endpoint = None
|
||||
|
||||
@ -134,7 +133,6 @@ class BaseImageService(object):
|
||||
retry the request according to CONF.glance_num_retries.
|
||||
|
||||
:param context: The request context, for access checks.
|
||||
:param version: The requested API version.v
|
||||
:param method: The method requested to be called.
|
||||
:param args: A list of positional arguments for the method called
|
||||
:param kwargs: A dict of keyword arguments for the method called
|
||||
@ -208,9 +206,7 @@ class BaseImageService(object):
|
||||
"""
|
||||
image_id = service_utils.parse_image_id(image_href)
|
||||
|
||||
if (self.version == 2
|
||||
and 'file' in CONF.glance.allowed_direct_url_schemes):
|
||||
|
||||
if 'file' in CONF.glance.allowed_direct_url_schemes:
|
||||
location = self._get_location(image_id)
|
||||
url = urlparse.urlparse(location)
|
||||
if url.scheme == "file":
|
||||
@ -222,10 +218,7 @@ class BaseImageService(object):
|
||||
image_chunks = self.call(method, image_id)
|
||||
# NOTE(dtantsur): when using Glance V2, image_chunks is a wrapper
|
||||
# around real data, so we have to check the wrapped data for None.
|
||||
# Glance V1 returns HTTP 404 in this case, so no need to fix it.
|
||||
# TODO(dtantsur): remove the hasattr check when we no longer support
|
||||
# Glance V1.
|
||||
if hasattr(image_chunks, 'wrapped') and image_chunks.wrapped is None:
|
||||
if image_chunks.wrapped is None:
|
||||
raise exception.ImageDownloadFailed(
|
||||
image_href=image_href, reason=_('image contains no data.'))
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import abc
|
||||
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class ImageService(object):
|
||||
"""Provides storage and retrieval of disk image objects within Glance."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __init__(self):
|
||||
"""Constructor."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def show(self, image_id):
|
||||
"""Returns a dict with image data for the given opaque image id.
|
||||
|
||||
:param image_id: The opaque image identifier.
|
||||
:returns: A dict containing image metadata.
|
||||
|
||||
:raises: ImageNotFound
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def download(self, image_id, data=None):
|
||||
"""Calls out to Glance for data and writes data.
|
||||
|
||||
:param image_id: The opaque image identifier.
|
||||
:param data: (Optional) File object to write data to.
|
||||
"""
|
@ -23,10 +23,8 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common import image_service
|
||||
from ironic.conf import CONF
|
||||
|
||||
|
||||
@ -36,31 +34,24 @@ _GLANCE_API_SERVER = None
|
||||
""" iterator that cycles (indefinitely) over glance API servers. """
|
||||
|
||||
|
||||
_IMAGE_ATTRIBUTES = ['size', 'disk_format', 'owner',
|
||||
'container_format', 'checksum', 'id',
|
||||
'name', 'created_at', 'updated_at',
|
||||
'deleted_at', 'deleted', 'status',
|
||||
'min_disk', 'min_ram', 'tags', 'visibility',
|
||||
'protected', 'file', 'schema']
|
||||
|
||||
|
||||
def _extract_attributes(image):
|
||||
# TODO(pas-ha) in Queens unify these once GlanceV1 is no longer supported
|
||||
IMAGE_ATTRIBUTES = ['size', 'disk_format', 'owner',
|
||||
'container_format', 'checksum', 'id',
|
||||
'name', 'created_at', 'updated_at',
|
||||
'deleted_at', 'deleted', 'status',
|
||||
'min_disk', 'min_ram', 'is_public']
|
||||
|
||||
IMAGE_ATTRIBUTES_V2 = ['tags', 'visibility', 'protected',
|
||||
'file', 'schema']
|
||||
|
||||
output = {}
|
||||
for attr in IMAGE_ATTRIBUTES:
|
||||
for attr in _IMAGE_ATTRIBUTES:
|
||||
output[attr] = getattr(image, attr, None)
|
||||
|
||||
output['properties'] = getattr(image, 'properties', {})
|
||||
output['properties'] = {}
|
||||
output['schema'] = image.schema
|
||||
|
||||
if hasattr(image, 'schema') and 'v2' in image['schema']:
|
||||
IMAGE_ATTRIBUTES = IMAGE_ATTRIBUTES + IMAGE_ATTRIBUTES_V2
|
||||
for attr in IMAGE_ATTRIBUTES_V2:
|
||||
output[attr] = getattr(image, attr, None)
|
||||
output['schema'] = image['schema']
|
||||
|
||||
for image_property in set(image) - set(IMAGE_ATTRIBUTES):
|
||||
output['properties'][image_property] = image[image_property]
|
||||
for image_property in set(image) - set(_IMAGE_ATTRIBUTES):
|
||||
output['properties'][image_property] = image[image_property]
|
||||
|
||||
return output
|
||||
|
||||
@ -154,23 +145,11 @@ def is_image_available(context, image):
|
||||
if hasattr(context, 'auth_token') and context.auth_token:
|
||||
return True
|
||||
|
||||
if ((getattr(image, 'is_public', None)
|
||||
or getattr(image, 'visibility', None) == 'public')
|
||||
or context.is_admin):
|
||||
if getattr(image, 'visibility', None) == 'public' or context.is_admin:
|
||||
return True
|
||||
properties = image.properties
|
||||
if context.project_id and ('owner_id' in properties):
|
||||
return str(properties['owner_id']) == str(context.project_id)
|
||||
|
||||
if context.project_id and ('project_id' in properties):
|
||||
return str(properties['project_id']) == str(context.project_id)
|
||||
|
||||
try:
|
||||
user_id = properties['user_id']
|
||||
except KeyError:
|
||||
return False
|
||||
|
||||
return str(user_id) == str(context.user_id)
|
||||
return (context.project_id and
|
||||
getattr(image, 'owner', None) == context.project_id)
|
||||
|
||||
|
||||
def is_image_active(image):
|
||||
@ -187,18 +166,3 @@ def is_glance_image(image_href):
|
||||
return False
|
||||
return (image_href.startswith('glance://')
|
||||
or uuidutils.is_uuid_like(image_href))
|
||||
|
||||
|
||||
def is_image_href_ordinary_file_name(image_href):
|
||||
"""Check if image_href is a ordinary file name.
|
||||
|
||||
This method judges if image_href is an ordinary file name or not,
|
||||
which is a file supposed to be stored in share file system.
|
||||
The ordinary file name is neither glance image href
|
||||
nor image service href.
|
||||
|
||||
:returns: True if image_href is ordinary file name, False otherwise.
|
||||
"""
|
||||
return not (is_glance_image(image_href)
|
||||
or urlparse.urlparse(image_href).scheme.lower() in
|
||||
image_service.protocol_mapping)
|
||||
|
@ -1,28 +0,0 @@
|
||||
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from ironic.common.glance_service import base_image_service
|
||||
from ironic.common.glance_service import service
|
||||
|
||||
|
||||
class GlanceImageService(base_image_service.BaseImageService,
|
||||
service.ImageService):
|
||||
|
||||
def show(self, image_id):
|
||||
return self._show(image_id, method='get')
|
||||
|
||||
def download(self, image_id, data=None):
|
||||
return self._download(image_id, method='data', data=data)
|
@ -23,7 +23,6 @@ from swiftclient import utils as swift_utils
|
||||
|
||||
from ironic.common import exception as exc
|
||||
from ironic.common.glance_service import base_image_service
|
||||
from ironic.common.glance_service import service
|
||||
from ironic.common.glance_service import service_utils
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import keystone
|
||||
@ -34,8 +33,7 @@ TempUrlCacheElement = collections.namedtuple('TempUrlCacheElement',
|
||||
['url', 'url_expires_at'])
|
||||
|
||||
|
||||
class GlanceImageService(base_image_service.BaseImageService,
|
||||
service.ImageService):
|
||||
class GlanceImageService(base_image_service.BaseImageService):
|
||||
|
||||
# A dictionary containing cached temp URLs in namedtuples
|
||||
# in format:
|
||||
|
@ -21,7 +21,6 @@ import os
|
||||
import shutil
|
||||
|
||||
from oslo_log import log
|
||||
from oslo_utils import importutils
|
||||
from oslo_utils import uuidutils
|
||||
import requests
|
||||
import sendfile
|
||||
@ -30,25 +29,16 @@ from six.moves import http_client
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common.glance_service.v2 import image_service
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import utils
|
||||
from ironic.conf import CONF
|
||||
|
||||
IMAGE_CHUNK_SIZE = 1024 * 1024 # 1mb
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO(pas-ha) in Queens change default to '2',
|
||||
# but keep the versioned import in place (less work for possible Glance v3)
|
||||
def GlanceImageService(client=None, version=None, context=None):
|
||||
module_str = 'ironic.common.glance_service'
|
||||
if version is None:
|
||||
version = CONF.glance.glance_api_version
|
||||
|
||||
module = importutils.import_versioned_module(module_str, version,
|
||||
'image_service')
|
||||
service_class = getattr(module, 'GlanceImageService')
|
||||
return service_class(client, version, context)
|
||||
# TODO(dtantsur): temporary re-import, refactor the code and remove it.
|
||||
GlanceImageService = image_service.GlanceImageService
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
@ -255,14 +245,12 @@ protocol_mapping = {
|
||||
}
|
||||
|
||||
|
||||
def get_image_service(image_href, client=None, version=None, context=None):
|
||||
def get_image_service(image_href, client=None, context=None):
|
||||
"""Get image service instance to download the image.
|
||||
|
||||
:param image_href: String containing href to get image service for.
|
||||
:param client: Glance client to be used for download, used only if
|
||||
image_href is Glance href.
|
||||
:param version: Version of Glance API to use, used only if image_href is
|
||||
Glance href.
|
||||
:param context: request context, used only if image_href is Glance href.
|
||||
:raises: exception.ImageRefValidationFailed if no image service can
|
||||
handle specified href.
|
||||
@ -287,5 +275,5 @@ def get_image_service(image_href, client=None, version=None, context=None):
|
||||
) % scheme)
|
||||
|
||||
if cls == GlanceImageService:
|
||||
return cls(client, version, context)
|
||||
return cls(client, context)
|
||||
return cls()
|
||||
|
@ -406,8 +406,7 @@ def get_temp_url_for_glance_image(context, image_uuid):
|
||||
:param image_uuid: the UUID of the image in glance
|
||||
:returns: the tmp url for the glance image.
|
||||
"""
|
||||
# Glance API version 2 is required for getting direct_url of the image.
|
||||
glance_service = service.GlanceImageService(version=2, context=context)
|
||||
glance_service = service.GlanceImageService(context=context)
|
||||
image_properties = glance_service.show(image_uuid)
|
||||
LOG.debug('Got image info: %(info)s for image %(image_uuid)s.',
|
||||
{'info': image_properties, 'image_uuid': image_uuid})
|
||||
|
@ -505,8 +505,7 @@ def get_instance_image_info(node, ctx):
|
||||
labels = ('kernel', 'ramdisk')
|
||||
d_info = deploy_utils.get_image_instance_info(node)
|
||||
if not (i_info.get('kernel') and i_info.get('ramdisk')):
|
||||
glance_service = service.GlanceImageService(
|
||||
version=CONF.glance.glance_api_version, context=ctx)
|
||||
glance_service = service.GlanceImageService(context=ctx)
|
||||
iproperties = glance_service.show(d_info['image_source'])['properties']
|
||||
for label in labels:
|
||||
i_info[label] = str(iproperties[label + '_id'])
|
||||
|
@ -143,12 +143,6 @@ opts = [
|
||||
help=_('Optional path to a CA certificate bundle to be used to '
|
||||
'validate the SSL certificate served by glance. It is '
|
||||
'used when glance_api_insecure is set to False.')),
|
||||
cfg.IntOpt('glance_api_version',
|
||||
help=_('Glance API version (1 or 2) to use.'),
|
||||
min=1, max=2, default=2,
|
||||
deprecated_for_removal=True,
|
||||
deprecated_reason=_('Ironic will only support using Glance API '
|
||||
'version 2 in the Queens release.')),
|
||||
]
|
||||
|
||||
|
||||
|
@ -1196,8 +1196,7 @@ def build_instance_info_for_deploy(task):
|
||||
image_source = instance_info['image_source']
|
||||
|
||||
if service_utils.is_glance_image(image_source):
|
||||
glance = image_service.GlanceImageService(version=2,
|
||||
context=task.context)
|
||||
glance = image_service.GlanceImageService(context=task.context)
|
||||
image_info = glance.show(image_source)
|
||||
LOG.debug('Got image info: %(info)s for node %(node)s.',
|
||||
{'info': image_info, 'node': node.uuid})
|
||||
|
@ -24,11 +24,13 @@ from ironic_lib import metrics_utils
|
||||
from ironic_lib import utils as ironic_utils
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import importutils
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
from ironic.common import boot_devices
|
||||
from ironic.common import exception
|
||||
from ironic.common.glance_service import service_utils
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import image_service
|
||||
from ironic.common import images
|
||||
from ironic.common import states
|
||||
from ironic.conductor import utils as manager_utils
|
||||
@ -84,6 +86,21 @@ COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
|
||||
COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
|
||||
|
||||
|
||||
def _is_image_href_ordinary_file_name(image_href):
|
||||
"""Check if image_href is a ordinary file name.
|
||||
|
||||
This method judges if image_href is an ordinary file name or not,
|
||||
which is a file supposed to be stored in share file system.
|
||||
The ordinary file name is neither glance image href
|
||||
nor image service href.
|
||||
|
||||
:returns: True if image_href is ordinary file name, False otherwise.
|
||||
"""
|
||||
return not (service_utils.is_glance_image(image_href)
|
||||
or urlparse.urlparse(image_href).scheme.lower() in
|
||||
image_service.protocol_mapping)
|
||||
|
||||
|
||||
def _parse_config_option():
|
||||
"""Parse config file options.
|
||||
|
||||
@ -134,7 +151,7 @@ def _parse_driver_info(node, mode='deploy'):
|
||||
"parameters were missing in node's driver_info") % mode)
|
||||
deploy_utils.check_for_missing_params(deploy_info, error_msg)
|
||||
|
||||
if service_utils.is_image_href_ordinary_file_name(image_iso):
|
||||
if _is_image_href_ordinary_file_name(image_iso):
|
||||
image_iso_file = os.path.join(CONF.irmc.remote_image_share_root,
|
||||
image_iso)
|
||||
if not os.path.isfile(image_iso_file):
|
||||
@ -166,7 +183,7 @@ def _parse_instance_info(node):
|
||||
if i_info.get('irmc_boot_iso'):
|
||||
deploy_info['irmc_boot_iso'] = i_info['irmc_boot_iso']
|
||||
|
||||
if service_utils.is_image_href_ordinary_file_name(
|
||||
if _is_image_href_ordinary_file_name(
|
||||
deploy_info['irmc_boot_iso']):
|
||||
boot_iso = os.path.join(CONF.irmc.remote_image_share_root,
|
||||
deploy_info['irmc_boot_iso'])
|
||||
@ -227,7 +244,7 @@ def _setup_vmedia(task, mode, ramdisk_options):
|
||||
else:
|
||||
iso = task.node.driver_info['irmc_deploy_iso']
|
||||
|
||||
if service_utils.is_image_href_ordinary_file_name(iso):
|
||||
if _is_image_href_ordinary_file_name(iso):
|
||||
iso_file = iso
|
||||
else:
|
||||
iso_file = _get_iso_name(task.node, label=mode)
|
||||
@ -266,7 +283,7 @@ def _prepare_boot_iso(task, root_uuid):
|
||||
# fetch boot iso
|
||||
if deploy_info.get('irmc_boot_iso'):
|
||||
boot_iso_href = deploy_info['irmc_boot_iso']
|
||||
if service_utils.is_image_href_ordinary_file_name(boot_iso_href):
|
||||
if _is_image_href_ordinary_file_name(boot_iso_href):
|
||||
driver_internal_info['irmc_boot_iso'] = boot_iso_href
|
||||
else:
|
||||
boot_iso_filename = _get_iso_name(task.node, label='boot')
|
||||
|
@ -48,7 +48,6 @@ class NullWriter(object):
|
||||
class TestGlanceSerializer(testtools.TestCase):
|
||||
def test_serialize(self):
|
||||
metadata = {'name': 'image1',
|
||||
'is_public': True,
|
||||
'foo': 'bar',
|
||||
'properties': {
|
||||
'prop1': 'propvalue1',
|
||||
@ -62,7 +61,6 @@ class TestGlanceSerializer(testtools.TestCase):
|
||||
|
||||
expected = {
|
||||
'name': 'image1',
|
||||
'is_public': True,
|
||||
'foo': 'bar',
|
||||
'properties': {'prop1': 'propvalue1',
|
||||
'mappings': [
|
||||
@ -95,7 +93,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
self.context = context.RequestContext(auth_token=True)
|
||||
self.context.user_id = 'fake'
|
||||
self.context.project_id = 'fake'
|
||||
self.service = service.GlanceImageService(self.client, 2, self.context)
|
||||
self.service = service.GlanceImageService(self.client, self.context)
|
||||
|
||||
self.config(glance_api_servers=['http://localhost'], group='glance')
|
||||
self.config(auth_strategy='keystone', group='glance')
|
||||
@ -103,9 +101,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
@staticmethod
|
||||
def _make_fixture(**kwargs):
|
||||
fixture = {'name': None,
|
||||
'properties': {},
|
||||
'status': "active",
|
||||
'is_public': None}
|
||||
'status': "active"}
|
||||
fixture.update(kwargs)
|
||||
return stubs.FakeImage(fixture)
|
||||
|
||||
@ -128,25 +124,28 @@ class TestGlanceImageService(base.TestCase):
|
||||
|
||||
def test_show_passes_through_to_client(self):
|
||||
image_id = uuidutils.generate_uuid()
|
||||
image = self._make_fixture(name='image1', is_public=True,
|
||||
id=image_id)
|
||||
image = self._make_fixture(name='image1', id=image_id)
|
||||
expected = {
|
||||
'checksum': None,
|
||||
'container_format': None,
|
||||
'created_at': None,
|
||||
'deleted': None,
|
||||
'deleted_at': None,
|
||||
'disk_format': None,
|
||||
'file': None,
|
||||
'id': image_id,
|
||||
'name': 'image1',
|
||||
'is_public': True,
|
||||
'size': None,
|
||||
'min_disk': None,
|
||||
'min_ram': None,
|
||||
'disk_format': None,
|
||||
'container_format': None,
|
||||
'checksum': None,
|
||||
'created_at': None,
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
'deleted': None,
|
||||
'status': "active",
|
||||
'properties': {},
|
||||
'name': 'image1',
|
||||
'owner': None,
|
||||
'properties': {},
|
||||
'protected': None,
|
||||
'schema': None,
|
||||
'size': None,
|
||||
'status': "active",
|
||||
'tags': None,
|
||||
'updated_at': None,
|
||||
'visibility': None,
|
||||
}
|
||||
with mock.patch.object(self.service, 'call', return_value=image,
|
||||
autospec=True):
|
||||
@ -172,8 +171,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
|
||||
def test_show_raises_when_image_not_active(self):
|
||||
image_id = uuidutils.generate_uuid()
|
||||
image = self._make_fixture(name='image1', is_public=True,
|
||||
id=image_id, status="queued")
|
||||
image = self._make_fixture(name='image1', id=image_id, status="queued")
|
||||
with mock.patch.object(self.service, 'call', return_value=image,
|
||||
autospec=True):
|
||||
self.assertRaises(exception.ImageUnacceptable,
|
||||
@ -196,7 +194,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_context = context.RequestContext(auth_token=True)
|
||||
stub_context.user_id = 'fake'
|
||||
stub_context.project_id = 'fake'
|
||||
stub_service = service.GlanceImageService(stub_client, 1, stub_context)
|
||||
stub_service = service.GlanceImageService(stub_client, stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
writer = NullWriter()
|
||||
|
||||
@ -243,8 +241,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_client = MyGlanceStubClient()
|
||||
|
||||
stub_service = service.GlanceImageService(stub_client,
|
||||
context=stub_context,
|
||||
version=2)
|
||||
context=stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
|
||||
self.config(allowed_direct_url_schemes=['file'], group='glance')
|
||||
@ -279,7 +276,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_context = context.RequestContext(auth_token=True)
|
||||
stub_context.user_id = 'fake'
|
||||
stub_context.project_id = 'fake'
|
||||
stub_service = service.GlanceImageService(stub_client, 1, stub_context)
|
||||
stub_service = service.GlanceImageService(stub_client, stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
writer = NullWriter()
|
||||
self.assertRaises(exception.ImageNotAuthorized, stub_service.download,
|
||||
@ -295,7 +292,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_context = context.RequestContext(auth_token=True)
|
||||
stub_context.user_id = 'fake'
|
||||
stub_context.project_id = 'fake'
|
||||
stub_service = service.GlanceImageService(stub_client, 1, stub_context)
|
||||
stub_service = service.GlanceImageService(stub_client, stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
writer = NullWriter()
|
||||
self.assertRaises(exception.ImageNotAuthorized, stub_service.download,
|
||||
@ -311,7 +308,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_context = context.RequestContext(auth_token=True)
|
||||
stub_context.user_id = 'fake'
|
||||
stub_context.project_id = 'fake'
|
||||
stub_service = service.GlanceImageService(stub_client, 1, stub_context)
|
||||
stub_service = service.GlanceImageService(stub_client, stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
writer = NullWriter()
|
||||
self.assertRaises(exception.ImageNotFound, stub_service.download,
|
||||
@ -327,7 +324,7 @@ class TestGlanceImageService(base.TestCase):
|
||||
stub_context = context.RequestContext(auth_token=True)
|
||||
stub_context.user_id = 'fake'
|
||||
stub_context.project_id = 'fake'
|
||||
stub_service = service.GlanceImageService(stub_client, 1, stub_context)
|
||||
stub_service = service.GlanceImageService(stub_client, stub_context)
|
||||
image_id = uuidutils.generate_uuid()
|
||||
writer = NullWriter()
|
||||
self.assertRaises(exception.ImageNotFound, stub_service.download,
|
||||
@ -346,7 +343,7 @@ class CheckImageServiceTestCase(base.TestCase):
|
||||
def setUp(self):
|
||||
super(CheckImageServiceTestCase, self).setUp()
|
||||
self.context = context.RequestContext(global_request_id='global')
|
||||
self.service = service.GlanceImageService(None, 1, self.context)
|
||||
self.service = service.GlanceImageService(None, self.context)
|
||||
# NOTE(pas-ha) register keystoneauth dynamic options manually
|
||||
plugin = kaloading.get_plugin_loader('password')
|
||||
opts = kaloading.get_auth_plugin_conf_options(plugin)
|
||||
@ -381,7 +378,7 @@ class CheckImageServiceTestCase(base.TestCase):
|
||||
|
||||
def _assert_client_call(self, mock_gclient, url, user=False):
|
||||
mock_gclient.assert_called_once_with(
|
||||
1,
|
||||
2,
|
||||
session=mock.sentinel.session,
|
||||
global_request_id='global',
|
||||
auth=mock.sentinel.sauth if user else mock.sentinel.auth,
|
||||
@ -504,7 +501,7 @@ class TestGlanceSwiftTempURL(base.TestCase):
|
||||
client = stubs.StubGlanceClient()
|
||||
self.context = context.RequestContext()
|
||||
self.context.auth_token = 'fake'
|
||||
self.service = service.GlanceImageService(client, 2, self.context)
|
||||
self.service = service.GlanceImageService(client, self.context)
|
||||
self.config(swift_temp_url_key='correcthorsebatterystaple',
|
||||
group='glance')
|
||||
self.config(swift_endpoint_url='https://swift.example.com',
|
||||
@ -769,7 +766,7 @@ class TestSwiftTempUrlCache(base.TestCase):
|
||||
group='glance')
|
||||
self.config(swift_store_multiple_containers_seed=0,
|
||||
group='glance')
|
||||
self.glance_service = service.GlanceImageService(client, version=2,
|
||||
self.glance_service = service.GlanceImageService(client,
|
||||
context=self.context)
|
||||
|
||||
@mock.patch('swiftclient.utils.generate_temp_url', autospec=True)
|
||||
@ -1004,17 +1001,3 @@ class TestServiceUtils(base.TestCase):
|
||||
self.assertFalse(service_utils.is_glance_image(image_href))
|
||||
image_href = None
|
||||
self.assertFalse(service_utils.is_glance_image(image_href))
|
||||
|
||||
def test_is_image_href_ordinary_file_name_true(self):
|
||||
image = u"\u0111eploy.iso"
|
||||
result = service_utils.is_image_href_ordinary_file_name(image)
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_is_image_href_ordinary_file_name_false(self):
|
||||
for image in ('733d1c44-a2ea-414b-aca7-69decf20d810',
|
||||
u'glance://\u0111eploy_iso',
|
||||
u'http://\u0111eploy_iso',
|
||||
u'https://\u0111eploy_iso',
|
||||
u'file://\u0111eploy_iso',):
|
||||
result = service_utils.is_image_href_ordinary_file_name(image)
|
||||
self.assertFalse(result)
|
||||
|
@ -24,7 +24,6 @@ import six.moves.builtins as __builtin__
|
||||
from six.moves import http_client
|
||||
|
||||
from ironic.common import exception
|
||||
from ironic.common.glance_service.v1 import image_service as glance_v1_service
|
||||
from ironic.common.glance_service.v2 import image_service as glance_v2_service
|
||||
from ironic.common import image_service
|
||||
from ironic.tests import base
|
||||
@ -271,16 +270,7 @@ class ServiceGetterTestCase(base.TestCase):
|
||||
def test_get_glance_image_service(self, glance_service_mock):
|
||||
image_href = uuidutils.generate_uuid()
|
||||
image_service.get_image_service(image_href, context=self.context)
|
||||
glance_service_mock.assert_called_once_with(mock.ANY, None, 2,
|
||||
self.context)
|
||||
|
||||
@mock.patch.object(glance_v1_service.GlanceImageService, '__init__',
|
||||
return_value=None, autospec=True)
|
||||
def test_get_glance_image_service_default_v1(self, glance_service_mock):
|
||||
self.config(glance_api_version=1, group='glance')
|
||||
image_href = uuidutils.generate_uuid()
|
||||
image_service.get_image_service(image_href, context=self.context)
|
||||
glance_service_mock.assert_called_once_with(mock.ANY, None, 1,
|
||||
glance_service_mock.assert_called_once_with(mock.ANY, None,
|
||||
self.context)
|
||||
|
||||
@mock.patch.object(glance_v2_service.GlanceImageService, '__init__',
|
||||
@ -288,7 +278,7 @@ class ServiceGetterTestCase(base.TestCase):
|
||||
def test_get_glance_image_service_url(self, glance_service_mock):
|
||||
image_href = 'glance://%s' % uuidutils.generate_uuid()
|
||||
image_service.get_image_service(image_href, context=self.context)
|
||||
glance_service_mock.assert_called_once_with(mock.ANY, None, 2,
|
||||
glance_service_mock.assert_called_once_with(mock.ANY, None,
|
||||
self.context)
|
||||
|
||||
@mock.patch.object(image_service.HttpImageService, '__init__',
|
||||
|
@ -40,6 +40,7 @@ from ironic.drivers.modules.irmc import boot as irmc_boot
|
||||
from ironic.drivers.modules.irmc import common as irmc_common
|
||||
from ironic.drivers.modules.irmc import management as irmc_management
|
||||
from ironic.drivers.modules import pxe
|
||||
from ironic.tests import base
|
||||
from ironic.tests.unit.db import utils as db_utils
|
||||
from ironic.tests.unit.drivers.modules.irmc import test_common
|
||||
from ironic.tests.unit.drivers.modules import test_pxe
|
||||
@ -117,7 +118,7 @@ class IRMCDeployPrivateMethodsTestCase(test_common.BaseIRMCTest):
|
||||
'/remote_image_share_root/deploy.iso')
|
||||
self.assertEqual(driver_info_expected, driver_info_actual)
|
||||
|
||||
@mock.patch.object(service_utils, 'is_image_href_ordinary_file_name',
|
||||
@mock.patch.object(irmc_boot, '_is_image_href_ordinary_file_name',
|
||||
spec_set=True, autospec=True)
|
||||
def test__parse_driver_info_not_in_share(
|
||||
self, is_image_href_ordinary_file_name_mock):
|
||||
@ -427,7 +428,7 @@ class IRMCDeployPrivateMethodsTestCase(test_common.BaseIRMCTest):
|
||||
autospec=True)
|
||||
@mock.patch.object(irmc_boot, '_parse_deploy_info', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(service_utils, 'is_image_href_ordinary_file_name',
|
||||
@mock.patch.object(irmc_boot, '_is_image_href_ordinary_file_name',
|
||||
spec_set=True, autospec=True)
|
||||
def test__prepare_boot_iso_fetch_ok(self,
|
||||
is_image_href_ordinary_file_name_mock,
|
||||
@ -1893,3 +1894,20 @@ class IRMCPXEBootBasicTestCase(test_pxe.PXEBootTestCase):
|
||||
properties = task.driver.get_properties()
|
||||
for p in pxe.COMMON_PROPERTIES:
|
||||
self.assertIn(p, properties)
|
||||
|
||||
|
||||
class IsImageHrefOrdinaryFileNameTestCase(base.TestCase):
|
||||
|
||||
def test_is_image_href_ordinary_file_name_true(self):
|
||||
image = u"\u0111eploy.iso"
|
||||
result = irmc_boot._is_image_href_ordinary_file_name(image)
|
||||
self.assertTrue(result)
|
||||
|
||||
def test_is_image_href_ordinary_file_name_false(self):
|
||||
for image in ('733d1c44-a2ea-414b-aca7-69decf20d810',
|
||||
u'glance://\u0111eploy_iso',
|
||||
u'http://\u0111eploy_iso',
|
||||
u'https://\u0111eploy_iso',
|
||||
u'file://\u0111eploy_iso',):
|
||||
result = irmc_boot._is_image_href_ordinary_file_name(image)
|
||||
self.assertFalse(result)
|
||||
|
@ -2257,8 +2257,7 @@ class TestBuildInstanceInfoForDeploy(db_base.DbTestCase):
|
||||
|
||||
utils.build_instance_info_for_deploy(task)
|
||||
|
||||
glance_mock.assert_called_once_with(version=2,
|
||||
context=task.context)
|
||||
glance_mock.assert_called_once_with(context=task.context)
|
||||
glance_mock.return_value.show.assert_called_once_with(
|
||||
self.node.instance_info['image_source'])
|
||||
glance_mock.return_value.swift_temp_url.assert_called_once_with(
|
||||
@ -2318,8 +2317,7 @@ class TestBuildInstanceInfoForDeploy(db_base.DbTestCase):
|
||||
|
||||
info = utils.build_instance_info_for_deploy(task)
|
||||
|
||||
glance_mock.assert_called_once_with(version=2,
|
||||
context=task.context)
|
||||
glance_mock.assert_called_once_with(context=task.context)
|
||||
glance_mock.return_value.show.assert_called_once_with(
|
||||
self.node.instance_info['image_source'])
|
||||
glance_mock.return_value.swift_temp_url.assert_called_once_with(
|
||||
@ -2474,8 +2472,7 @@ class TestBuildInstanceInfoForHttpProvisioning(db_base.DbTestCase):
|
||||
|
||||
instance_info = utils.build_instance_info_for_deploy(task)
|
||||
|
||||
glance_mock.assert_called_once_with(version=2,
|
||||
context=task.context)
|
||||
glance_mock.assert_called_once_with(context=task.context)
|
||||
glance_mock.return_value.show.assert_called_once_with(
|
||||
self.node.instance_info['image_source'])
|
||||
self.cache_image_mock.assert_called_once_with(task.context,
|
||||
@ -2511,8 +2508,7 @@ class TestBuildInstanceInfoForHttpProvisioning(db_base.DbTestCase):
|
||||
|
||||
instance_info = utils.build_instance_info_for_deploy(task)
|
||||
|
||||
glance_mock.assert_called_once_with(version=2,
|
||||
context=task.context)
|
||||
glance_mock.assert_called_once_with(context=task.context)
|
||||
glance_mock.return_value.show.assert_called_once_with(
|
||||
self.node.instance_info['image_source'])
|
||||
self.cache_image_mock.assert_called_once_with(task.context,
|
||||
|
@ -51,27 +51,27 @@ class StubGlanceClient(object):
|
||||
return _GlanceWrapper(self.fake_wrapped)
|
||||
|
||||
|
||||
class FakeImage(object):
|
||||
class FakeImage(dict):
|
||||
def __init__(self, metadata):
|
||||
IMAGE_ATTRIBUTES = ['size', 'disk_format', 'owner',
|
||||
'container_format', 'checksum', 'id',
|
||||
'name',
|
||||
'deleted', 'status',
|
||||
'min_disk', 'min_ram', 'is_public']
|
||||
'name', 'deleted', 'status',
|
||||
'min_disk', 'min_ram', 'tags', 'visibility',
|
||||
'protected', 'file', 'schema']
|
||||
raw = dict.fromkeys(IMAGE_ATTRIBUTES)
|
||||
raw.update(metadata)
|
||||
# raw['created_at'] = NOW_GLANCE_FORMAT
|
||||
# raw['updated_at'] = NOW_GLANCE_FORMAT
|
||||
self.__dict__['raw'] = raw
|
||||
super(FakeImage, self).__init__(raw)
|
||||
|
||||
def __getattr__(self, key):
|
||||
try:
|
||||
return self.__dict__['raw'][key]
|
||||
return self[key]
|
||||
except KeyError:
|
||||
raise AttributeError(key)
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
try:
|
||||
self.__dict__['raw'][key] = value
|
||||
except KeyError:
|
||||
if key in self:
|
||||
self[key] = value
|
||||
else:
|
||||
raise AttributeError(key)
|
||||
|
8
releasenotes/notes/no-glance-v1-d249e8079f46f40c.yaml
Normal file
8
releasenotes/notes/no-glance-v1-d249e8079f46f40c.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
upgrade:
|
||||
- |
|
||||
Support for using the Image API v1 was removed. It was removed from Glance
|
||||
in the Rocky release.
|
||||
- |
|
||||
The deprecated option ``[glance]glance_api_version`` was removed. Only v2
|
||||
is now used.
|
Loading…
Reference in New Issue
Block a user