Remove 'nova.image.api' module
This doesn't exist for 'nova.volume' and no longer exists for 'nova.network'. There's only one image backend we support, so do like we've done elsewhere and just use 'nova.image.glance'. Change-Id: I7ca7d8a92dfbc7c8d0ee2f9e660eabaa7e220e2a Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
This commit is contained in:
parent
e69dbfa0d3
commit
5fc3b81fdf
@ -24,7 +24,7 @@ from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
import nova.image
|
||||
from nova.image import glance
|
||||
|
||||
|
||||
class ImageMetadataController(wsgi.Controller):
|
||||
@ -32,7 +32,7 @@ class ImageMetadataController(wsgi.Controller):
|
||||
|
||||
def __init__(self):
|
||||
super(ImageMetadataController, self).__init__()
|
||||
self.image_api = nova.image.API()
|
||||
self.image_api = glance.API()
|
||||
|
||||
def _get_image(self, context, image_id):
|
||||
try:
|
||||
|
@ -22,8 +22,7 @@ from nova.api.openstack.compute.views import images as views_images
|
||||
from nova.api.openstack import wsgi
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
import nova.image
|
||||
import nova.utils
|
||||
from nova.image import glance
|
||||
|
||||
|
||||
SUPPORTED_FILTERS = {
|
||||
@ -44,7 +43,7 @@ class ImagesController(wsgi.Controller):
|
||||
|
||||
def __init__(self):
|
||||
super(ImagesController, self).__init__()
|
||||
self._image_api = nova.image.API()
|
||||
self._image_api = glance.API()
|
||||
|
||||
def _get_filters(self, req):
|
||||
"""Return a dictionary of query param filters from the request.
|
||||
|
@ -40,7 +40,7 @@ import nova.conf
|
||||
from nova import context as nova_context
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova.image import api as image_api
|
||||
from nova.image import glance
|
||||
from nova.network import neutron
|
||||
from nova import objects
|
||||
from nova.policies import servers as server_policies
|
||||
@ -1236,7 +1236,7 @@ class ServersController(wsgi.Controller):
|
||||
|
||||
# build location of newly-created image entity
|
||||
image_id = str(image['id'])
|
||||
image_ref = image_api.API().generate_image_url(image_id, context)
|
||||
image_ref = glance.API().generate_image_url(image_id, context)
|
||||
|
||||
resp = webob.Response(status_int=202)
|
||||
resp.headers['Location'] = image_ref
|
||||
|
@ -59,7 +59,7 @@ from nova import exception
|
||||
from nova import exception_wrapper
|
||||
from nova import hooks
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.network import constants
|
||||
from nova.network import model as network_model
|
||||
from nova.network import neutron
|
||||
@ -289,7 +289,7 @@ class API(base.Base):
|
||||
|
||||
def __init__(self, image_api=None, network_api=None, volume_api=None,
|
||||
**kwargs):
|
||||
self.image_api = image_api or image.API()
|
||||
self.image_api = image_api or glance.API()
|
||||
self.network_api = network_api or neutron.API()
|
||||
self.volume_api = volume_api or cinder.API()
|
||||
self._placementclient = None # Lazy-load on first access.
|
||||
@ -462,7 +462,7 @@ class API(base.Base):
|
||||
# image (below) and not any image URIs that might have been
|
||||
# supplied.
|
||||
# TODO(jaypipes): Get rid of this silliness once we move to a real
|
||||
# Image object and hide all of that stuff within nova.image.api.
|
||||
# Image object and hide all of that stuff within nova.image.glance
|
||||
kernel_id = kernel_image['id']
|
||||
|
||||
if ramdisk_id is not None:
|
||||
|
@ -74,7 +74,7 @@ from nova import exception
|
||||
from nova import exception_wrapper
|
||||
from nova import hooks
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova import manager
|
||||
from nova.network import model as network_model
|
||||
from nova.network import neutron
|
||||
@ -569,7 +569,7 @@ class ComputeManager(manager.Manager):
|
||||
self.virtapi = ComputeVirtAPI(self)
|
||||
self.network_api = neutron.API()
|
||||
self.volume_api = cinder.API()
|
||||
self.image_api = image.API()
|
||||
self.image_api = glance.API()
|
||||
self._last_bw_usage_poll = 0
|
||||
self._bw_usage_supported = True
|
||||
self.compute_api = compute.API()
|
||||
|
@ -1214,7 +1214,7 @@ def create_image(context, instance, name, image_type, image_api,
|
||||
:param instance: nova.objects.instance.Instance object
|
||||
:param name: string for name of the snapshot
|
||||
:param image_type: snapshot | backup
|
||||
:param image_api: instance of nova.image.API
|
||||
:param image_api: instance of nova.image.glance.API
|
||||
:param extra_properties: dict of extra image properties to include
|
||||
|
||||
"""
|
||||
|
@ -20,7 +20,7 @@ import oslo_messaging as messaging
|
||||
from nova import baserpc
|
||||
from nova.conductor import rpcapi
|
||||
import nova.conf
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
@ -84,7 +84,7 @@ class ComputeTaskAPI(object):
|
||||
|
||||
def __init__(self):
|
||||
self.conductor_compute_rpcapi = rpcapi.ComputeTaskAPI()
|
||||
self.image_api = image.API()
|
||||
self.image_api = glance.API()
|
||||
|
||||
# TODO(stephenfin): Remove the 'reservations' parameter since we don't use
|
||||
# reservations anymore
|
||||
|
@ -45,7 +45,7 @@ from nova import context as nova_context
|
||||
from nova.db import base
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova import manager
|
||||
from nova.network import neutron
|
||||
from nova import notifications
|
||||
@ -239,7 +239,7 @@ class ComputeTaskManager(base.Base):
|
||||
super(ComputeTaskManager, self).__init__()
|
||||
self.compute_rpcapi = compute_rpcapi.ComputeAPI()
|
||||
self.volume_api = cinder.API()
|
||||
self.image_api = image.API()
|
||||
self.image_api = glance.API()
|
||||
self.network_api = neutron.API()
|
||||
self.servicegroup_api = servicegroup.API()
|
||||
self.query_client = query.SchedulerQueryClient()
|
||||
|
@ -28,7 +28,7 @@ from nova import conf
|
||||
from nova import context as nova_context
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image as nova_image
|
||||
from nova.image import glance
|
||||
from nova.network import constants as neutron_constants
|
||||
from nova.network import neutron
|
||||
from nova import objects
|
||||
@ -401,7 +401,7 @@ class PrepResizeAtSourceTask(base.TaskBase):
|
||||
:param migration: Migration object from the source cell
|
||||
:param request_spec: RequestSpec object for the resize operation
|
||||
:param compute_rpcapi: instance of nova.compute.rpcapi.ComputeAPI
|
||||
:param image_api: instance of nova.image.api.API
|
||||
:param image_api: instance of nova.image.glance.API
|
||||
"""
|
||||
super(PrepResizeAtSourceTask, self).__init__(context, instance)
|
||||
self.migration = migration
|
||||
@ -636,7 +636,7 @@ class CrossCellMigrationTask(base.TaskBase):
|
||||
|
||||
self.network_api = neutron.API()
|
||||
self.volume_api = cinder.API()
|
||||
self.image_api = nova_image.API()
|
||||
self.image_api = glance.API()
|
||||
|
||||
# Keep an ordered dict of the sub-tasks completed so we can call their
|
||||
# rollback routines if something fails.
|
||||
|
@ -1,17 +0,0 @@
|
||||
# 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.
|
||||
|
||||
|
||||
def API():
|
||||
# Needed to prevent circular import...
|
||||
import nova.image.api
|
||||
return nova.image.api.API()
|
@ -1,199 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Main abstraction layer for retrieving and storing information about disk
|
||||
images used by the compute layer.
|
||||
"""
|
||||
|
||||
from nova.image import glance
|
||||
from nova import profiler
|
||||
|
||||
|
||||
@profiler.trace_cls("nova_image")
|
||||
class API(object):
|
||||
|
||||
"""Responsible for exposing a relatively stable internal API for other
|
||||
modules in Nova to retrieve information about disk images. This API
|
||||
attempts to match the nova.volume.api and nova.network.api calling
|
||||
interface.
|
||||
"""
|
||||
|
||||
def _get_session_and_image_id(self, context, id_or_uri):
|
||||
"""Returns a tuple of (session, image_id). If the supplied `id_or_uri`
|
||||
is an image ID, then the default client session will be returned
|
||||
for the context's user, along with the image ID. If the supplied
|
||||
`id_or_uri` parameter is a URI, then a client session connecting to
|
||||
the URI's image service endpoint will be returned along with a
|
||||
parsed image ID from that URI.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
"""
|
||||
return glance.get_remote_image_service(context, id_or_uri)
|
||||
|
||||
def _get_session(self, _context):
|
||||
"""Returns a client session that can be used to query for image
|
||||
information.
|
||||
|
||||
:param _context: The `nova.context.Context` object for the request
|
||||
"""
|
||||
# TODO(jaypipes): Refactor glance.get_remote_image_service and
|
||||
# glance.get_default_image_service into a single
|
||||
# method that takes a context and actually respects
|
||||
# it, returning a real session object that keeps
|
||||
# the context alive...
|
||||
return glance.get_default_image_service()
|
||||
|
||||
@staticmethod
|
||||
def generate_image_url(image_ref, context):
|
||||
"""Generate an image URL from an image_ref.
|
||||
|
||||
:param image_ref: The image ref to generate URL
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
"""
|
||||
return "%s/images/%s" % (next(glance.get_api_servers(context)),
|
||||
image_ref)
|
||||
|
||||
def get_all(self, context, **kwargs):
|
||||
"""Retrieves all information records about all disk images available
|
||||
to show to the requesting user. If the requesting user is an admin,
|
||||
all images in an ACTIVE status are returned. If the requesting user
|
||||
is not an admin, the all public images and all private images that
|
||||
are owned by the requesting user in the ACTIVE status are returned.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param kwargs: A dictionary of filter and pagination values that
|
||||
may be passed to the underlying image info driver.
|
||||
"""
|
||||
session = self._get_session(context)
|
||||
return session.detail(context, **kwargs)
|
||||
|
||||
def get(self, context, id_or_uri, include_locations=False,
|
||||
show_deleted=True):
|
||||
"""Retrieves the information record for a single disk image. If the
|
||||
supplied identifier parameter is a UUID, the default driver will
|
||||
be used to return information about the image. If the supplied
|
||||
identifier is a URI, then the driver that matches that URI endpoint
|
||||
will be used to query for image information.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param include_locations: (Optional) include locations in the returned
|
||||
dict of information if the image service API
|
||||
supports it. If the image service API does
|
||||
not support the locations attribute, it will
|
||||
still be included in the returned dict, as an
|
||||
empty list.
|
||||
:param show_deleted: (Optional) show the image even the status of
|
||||
image is deleted.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.show(context, image_id,
|
||||
include_locations=include_locations,
|
||||
show_deleted=show_deleted)
|
||||
|
||||
def create(self, context, image_info, data=None):
|
||||
"""Creates a new image record, optionally passing the image bits to
|
||||
backend storage.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param image_info: A dict of information about the image that is
|
||||
passed to the image registry.
|
||||
:param data: Optional file handle or bytestream iterator that is
|
||||
passed to backend storage.
|
||||
"""
|
||||
session = self._get_session(context)
|
||||
return session.create(context, image_info, data=data)
|
||||
|
||||
def update(self, context, id_or_uri, image_info,
|
||||
data=None, purge_props=False):
|
||||
"""Update the information about an image, optionally along with a file
|
||||
handle or bytestream iterator for image bits. If the optional file
|
||||
handle for updated image bits is supplied, the image may not have
|
||||
already uploaded bits for the image.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param image_info: A dict of information about the image that is
|
||||
passed to the image registry.
|
||||
:param data: Optional file handle or bytestream iterator that is
|
||||
passed to backend storage.
|
||||
:param purge_props: Optional, defaults to False. If set, the backend
|
||||
image registry will clear all image properties
|
||||
and replace them the image properties supplied
|
||||
in the image_info dictionary's 'properties'
|
||||
collection.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.update(context, image_id, image_info, data=data,
|
||||
purge_props=purge_props)
|
||||
|
||||
def delete(self, context, id_or_uri):
|
||||
"""Delete the information about an image and mark the image bits for
|
||||
deletion.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.delete(context, image_id)
|
||||
|
||||
def download(self, context, id_or_uri, data=None, dest_path=None,
|
||||
trusted_certs=None):
|
||||
"""Transfer image bits from Glance or a known source location to the
|
||||
supplied destination filepath.
|
||||
|
||||
:param context: The `nova.context.RequestContext` object for the
|
||||
request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param data: A file object to use in downloading image data.
|
||||
:param dest_path: Filepath to transfer image bits to.
|
||||
:param trusted_certs: A 'nova.objects.trusted_certs.TrustedCerts'
|
||||
object with a list of trusted image certificate
|
||||
IDs.
|
||||
|
||||
Note that because of the poor design of the
|
||||
`glance.ImageService.download` method, the function returns different
|
||||
things depending on what arguments are passed to it. If a data argument
|
||||
is supplied but no dest_path is specified (only done in the XenAPI virt
|
||||
driver's image.utils module) then None is returned from the method. If
|
||||
the data argument is not specified but a destination path *is*
|
||||
specified, then a writeable file handle to the destination path is
|
||||
constructed in the method and the image bits written to that file, and
|
||||
again, None is returned from the method. If no data argument is
|
||||
supplied and no dest_path argument is supplied (VMWare and XenAPI virt
|
||||
drivers), then the method returns an iterator to the image bits that
|
||||
the caller uses to write to wherever location it wants. Finally, if the
|
||||
allow_direct_url_schemes CONF option is set to something, then the
|
||||
nova.image.download modules are used to attempt to do an SCP copy of
|
||||
the image bits from a file location to the dest_path and None is
|
||||
returned after retrying one or more download locations (libvirt and
|
||||
Hyper-V virt drivers through nova.virt.images.fetch).
|
||||
|
||||
I think the above points to just how hacky/wacky all of this code is,
|
||||
and the reason it needs to be cleaned up and standardized across the
|
||||
virt driver callers.
|
||||
"""
|
||||
# TODO(jaypipes): Deprecate and remove this method entirely when we
|
||||
# move to a system that simply returns a file handle
|
||||
# to a bytestream iterator and allows the caller to
|
||||
# handle streaming/copying/zero-copy as they see fit.
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.download(context, image_id, data=data,
|
||||
dst_path=dest_path,
|
||||
trusted_certs=trusted_certs)
|
@ -48,6 +48,7 @@ from nova import exception
|
||||
import nova.image.download as image_xfers
|
||||
from nova import objects
|
||||
from nova.objects import fields
|
||||
from nova import profiler
|
||||
from nova import service_auth
|
||||
from nova import utils
|
||||
|
||||
@ -1012,7 +1013,181 @@ class UpdateGlanceImage(object):
|
||||
self.image_stream = stream
|
||||
|
||||
def start(self):
|
||||
image_service, image_id = (
|
||||
get_remote_image_service(self.context, self.image_id))
|
||||
image_service, image_id = get_remote_image_service(
|
||||
self.context, self.image_id)
|
||||
image_service.update(self.context, image_id, self.metadata,
|
||||
self.image_stream, purge_props=False)
|
||||
|
||||
|
||||
@profiler.trace_cls("nova_image")
|
||||
class API(object):
|
||||
"""API for interacting with the image service."""
|
||||
|
||||
def _get_session_and_image_id(self, context, id_or_uri):
|
||||
"""Returns a tuple of (session, image_id). If the supplied `id_or_uri`
|
||||
is an image ID, then the default client session will be returned
|
||||
for the context's user, along with the image ID. If the supplied
|
||||
`id_or_uri` parameter is a URI, then a client session connecting to
|
||||
the URI's image service endpoint will be returned along with a
|
||||
parsed image ID from that URI.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
"""
|
||||
return get_remote_image_service(context, id_or_uri)
|
||||
|
||||
def _get_session(self, _context):
|
||||
"""Returns a client session that can be used to query for image
|
||||
information.
|
||||
|
||||
:param _context: The `nova.context.Context` object for the request
|
||||
"""
|
||||
# TODO(jaypipes): Refactor get_remote_image_service and
|
||||
# get_default_image_service into a single
|
||||
# method that takes a context and actually respects
|
||||
# it, returning a real session object that keeps
|
||||
# the context alive...
|
||||
return get_default_image_service()
|
||||
|
||||
@staticmethod
|
||||
def generate_image_url(image_ref, context):
|
||||
"""Generate an image URL from an image_ref.
|
||||
|
||||
:param image_ref: The image ref to generate URL
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
"""
|
||||
return "%s/images/%s" % (next(get_api_servers(context)), image_ref)
|
||||
|
||||
def get_all(self, context, **kwargs):
|
||||
"""Retrieves all information records about all disk images available
|
||||
to show to the requesting user. If the requesting user is an admin,
|
||||
all images in an ACTIVE status are returned. If the requesting user
|
||||
is not an admin, the all public images and all private images that
|
||||
are owned by the requesting user in the ACTIVE status are returned.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param kwargs: A dictionary of filter and pagination values that
|
||||
may be passed to the underlying image info driver.
|
||||
"""
|
||||
session = self._get_session(context)
|
||||
return session.detail(context, **kwargs)
|
||||
|
||||
def get(self, context, id_or_uri, include_locations=False,
|
||||
show_deleted=True):
|
||||
"""Retrieves the information record for a single disk image. If the
|
||||
supplied identifier parameter is a UUID, the default driver will
|
||||
be used to return information about the image. If the supplied
|
||||
identifier is a URI, then the driver that matches that URI endpoint
|
||||
will be used to query for image information.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param include_locations: (Optional) include locations in the returned
|
||||
dict of information if the image service API
|
||||
supports it. If the image service API does
|
||||
not support the locations attribute, it will
|
||||
still be included in the returned dict, as an
|
||||
empty list.
|
||||
:param show_deleted: (Optional) show the image even the status of
|
||||
image is deleted.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.show(context, image_id,
|
||||
include_locations=include_locations,
|
||||
show_deleted=show_deleted)
|
||||
|
||||
def create(self, context, image_info, data=None):
|
||||
"""Creates a new image record, optionally passing the image bits to
|
||||
backend storage.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param image_info: A dict of information about the image that is
|
||||
passed to the image registry.
|
||||
:param data: Optional file handle or bytestream iterator that is
|
||||
passed to backend storage.
|
||||
"""
|
||||
session = self._get_session(context)
|
||||
return session.create(context, image_info, data=data)
|
||||
|
||||
def update(self, context, id_or_uri, image_info,
|
||||
data=None, purge_props=False):
|
||||
"""Update the information about an image, optionally along with a file
|
||||
handle or bytestream iterator for image bits. If the optional file
|
||||
handle for updated image bits is supplied, the image may not have
|
||||
already uploaded bits for the image.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param image_info: A dict of information about the image that is
|
||||
passed to the image registry.
|
||||
:param data: Optional file handle or bytestream iterator that is
|
||||
passed to backend storage.
|
||||
:param purge_props: Optional, defaults to False. If set, the backend
|
||||
image registry will clear all image properties
|
||||
and replace them the image properties supplied
|
||||
in the image_info dictionary's 'properties'
|
||||
collection.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.update(context, image_id, image_info, data=data,
|
||||
purge_props=purge_props)
|
||||
|
||||
def delete(self, context, id_or_uri):
|
||||
"""Delete the information about an image and mark the image bits for
|
||||
deletion.
|
||||
|
||||
:param context: The `nova.context.Context` object for the request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
"""
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.delete(context, image_id)
|
||||
|
||||
def download(self, context, id_or_uri, data=None, dest_path=None,
|
||||
trusted_certs=None):
|
||||
"""Transfer image bits from Glance or a known source location to the
|
||||
supplied destination filepath.
|
||||
|
||||
:param context: The `nova.context.RequestContext` object for the
|
||||
request
|
||||
:param id_or_uri: A UUID identifier or an image URI to look up image
|
||||
information for.
|
||||
:param data: A file object to use in downloading image data.
|
||||
:param dest_path: Filepath to transfer image bits to.
|
||||
:param trusted_certs: A 'nova.objects.trusted_certs.TrustedCerts'
|
||||
object with a list of trusted image certificate
|
||||
IDs.
|
||||
|
||||
Note that because of the poor design of the
|
||||
`glance.ImageService.download` method, the function returns different
|
||||
things depending on what arguments are passed to it. If a data argument
|
||||
is supplied but no dest_path is specified (only done in the XenAPI virt
|
||||
driver's image.utils module) then None is returned from the method. If
|
||||
the data argument is not specified but a destination path *is*
|
||||
specified, then a writeable file handle to the destination path is
|
||||
constructed in the method and the image bits written to that file, and
|
||||
again, None is returned from the method. If no data argument is
|
||||
supplied and no dest_path argument is supplied (VMWare and XenAPI virt
|
||||
drivers), then the method returns an iterator to the image bits that
|
||||
the caller uses to write to wherever location it wants. Finally, if the
|
||||
allow_direct_url_schemes CONF option is set to something, then the
|
||||
nova.image.download modules are used to attempt to do an SCP copy of
|
||||
the image bits from a file location to the dest_path and None is
|
||||
returned after retrying one or more download locations (libvirt and
|
||||
Hyper-V virt drivers through nova.virt.images.fetch).
|
||||
|
||||
I think the above points to just how hacky/wacky all of this code is,
|
||||
and the reason it needs to be cleaned up and standardized across the
|
||||
virt driver callers.
|
||||
"""
|
||||
# TODO(jaypipes): Deprecate and remove this method entirely when we
|
||||
# move to a system that simply returns a file handle
|
||||
# to a bytestream iterator and allows the caller to
|
||||
# handle streaming/copying/zero-copy as they see fit.
|
||||
session, image_id = self._get_session_and_image_id(context, id_or_uri)
|
||||
return session.download(context, image_id, data=data,
|
||||
dst_path=dest_path,
|
||||
trusted_certs=trusted_certs)
|
||||
|
@ -28,7 +28,7 @@ from oslo_utils import timeutils
|
||||
import nova.conf
|
||||
import nova.context
|
||||
from nova import exception
|
||||
from nova import image as image_api
|
||||
from nova.image import glance
|
||||
from nova.network import model as network_model
|
||||
from nova.network import neutron
|
||||
from nova.notifications.objects import base as notification_base
|
||||
@ -370,7 +370,7 @@ def info_from_instance(context, instance, network_info,
|
||||
# NOTE(mriedem): We can eventually drop this when we no longer
|
||||
# support legacy notifications since versioned notifications don't
|
||||
# use this.
|
||||
image_ref_url = image_api.API().generate_image_url(
|
||||
image_ref_url = glance.API().generate_image_url(
|
||||
instance.image_ref, context)
|
||||
|
||||
except ks_exc.EndpointNotFound:
|
||||
|
@ -194,7 +194,7 @@ class BootFromVolumeLargeRequestTest(test.TestCase,
|
||||
self.useFixture(nova_fixtures.NoopConductorFixture())
|
||||
# NOTE(gibi): Do not use 'c905cedb-7281-47e4-8a62-f26bc5fc4c77' image
|
||||
# as that is defined with a separate kernel image, leading to one extra
|
||||
# call to nova.image.api.API.get from compute.api
|
||||
# call to nova.image.glance.API.get from compute.api
|
||||
# _handle_kernel_and_ramdisk()
|
||||
image1 = 'a2459075-d96c-40d5-893e-577ff92e721c'
|
||||
image2 = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6'
|
||||
@ -217,7 +217,7 @@ class BootFromVolumeLargeRequestTest(test.TestCase,
|
||||
|
||||
# Wrap the image service get method to check how many times it was
|
||||
# called.
|
||||
with mock.patch('nova.image.api.API.get',
|
||||
with mock.patch('nova.image.glance.API.get',
|
||||
wraps=self.image_service.show) as mock_image_get:
|
||||
self.api.post_server({'server': server})
|
||||
# Assert that there was caching of the GET /v2/images/{image_id}
|
||||
|
@ -42,7 +42,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
super(ImageMetaDataTestV21, self).setUp()
|
||||
self.controller = self.controller_class()
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_index(self, get_all_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata')
|
||||
res_dict = self.controller.index(req, '123')
|
||||
@ -50,7 +50,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertEqual(res_dict, expected)
|
||||
get_all_mocked.assert_called_once_with(mock.ANY, '123')
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_show(self, get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
res_dict = self.controller.show(req, '123', 'key1')
|
||||
@ -59,13 +59,13 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertEqual('value1', res_dict['meta']['key1'])
|
||||
get_mocked.assert_called_once_with(mock.ANY, '123')
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_show_not_found(self, _get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key9')
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show, req, '123', 'key9')
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id='100'))
|
||||
def test_show_image_not_found(self, _get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '100/metadata/key1')
|
||||
@ -73,8 +73,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.controller.show, req, '100', 'key9')
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_create(self, get_mocked, update_mocked, quota_mocked):
|
||||
mock_result = copy.deepcopy(get_image_123())
|
||||
mock_result['properties']['key7'] = 'value7'
|
||||
@ -99,8 +99,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertEqual(expected_output, res)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id='100'))
|
||||
def test_create_image_not_found(self, _get_mocked, update_mocked,
|
||||
quota_mocked):
|
||||
@ -116,8 +116,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertFalse(update_mocked.called)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_update_all(self, get_mocked, update_mocked, quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata')
|
||||
req.method = 'PUT'
|
||||
@ -138,7 +138,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertEqual(expected_output, res)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id='100'))
|
||||
def test_update_all_image_not_found(self, _get_mocked, quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '100/metadata')
|
||||
@ -152,8 +152,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertFalse(quota_mocked.called)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_update_item(self, _get_mocked, update_mocked, quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
req.method = 'PUT'
|
||||
@ -173,7 +173,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertEqual(res, expected_output)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id='100'))
|
||||
def test_update_item_image_not_found(self, _get_mocked, quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '100/metadata/key1')
|
||||
@ -188,8 +188,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertFalse(quota_mocked.called)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get')
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get')
|
||||
def test_update_item_bad_body(self, get_mocked, update_mocked,
|
||||
quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
@ -207,8 +207,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR,
|
||||
side_effect=webob.exc.HTTPBadRequest())
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get')
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get')
|
||||
def test_update_item_too_many_keys(self, get_mocked, update_mocked,
|
||||
_quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
@ -224,8 +224,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertFalse(update_mocked.called)
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR)
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_update_item_body_uri_mismatch(self, _get_mocked, update_mocked,
|
||||
quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/bad')
|
||||
@ -240,8 +240,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertFalse(quota_mocked.called)
|
||||
self.assertFalse(update_mocked.called)
|
||||
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_delete(self, _get_mocked, update_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
req.method = 'DELETE'
|
||||
@ -253,7 +253,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
|
||||
self.assertIsNone(res)
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_delete_not_found(self, _get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/blah')
|
||||
req.method = 'DELETE'
|
||||
@ -261,7 +261,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.delete, req, '123', 'blah')
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id='100'))
|
||||
def test_delete_image_not_found(self, _get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '100/metadata/key1')
|
||||
@ -272,8 +272,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR,
|
||||
side_effect=webob.exc.HTTPForbidden(explanation=''))
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_too_many_metadata_items_on_create(self, _get_mocked,
|
||||
update_mocked, _quota_mocked):
|
||||
body = {"metadata": {"foo": "bar"}}
|
||||
@ -288,8 +288,8 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
|
||||
@mock.patch(CHK_QUOTA_STR,
|
||||
side_effect=webob.exc.HTTPForbidden(explanation=''))
|
||||
@mock.patch('nova.image.api.API.update')
|
||||
@mock.patch('nova.image.api.API.get', return_value=get_image_123())
|
||||
@mock.patch('nova.image.glance.API.update')
|
||||
@mock.patch('nova.image.glance.API.get', return_value=get_image_123())
|
||||
def test_too_many_metadata_items_on_put(self, _get_mocked,
|
||||
update_mocked, _quota_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/blah')
|
||||
@ -303,7 +303,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
body=body)
|
||||
self.assertFalse(update_mocked.called)
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotAuthorized(image_id='123'))
|
||||
def test_image_not_authorized_update(self, _get_mocked):
|
||||
req = fakes.HTTPRequest.blank(self.base_path + '123/metadata/key1')
|
||||
@ -316,7 +316,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.controller.update, req, '123', 'key1',
|
||||
body=body)
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotAuthorized(image_id='123'))
|
||||
def test_image_not_authorized_update_all(self, _get_mocked):
|
||||
image_id = 131
|
||||
@ -333,7 +333,7 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
|
||||
self.controller.update_all, req, image_id,
|
||||
body=body)
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotAuthorized(image_id='123'))
|
||||
def test_image_not_authorized_create(self, _get_mocked):
|
||||
image_id = 131
|
||||
|
@ -144,7 +144,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
},
|
||||
}
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=IMAGE_FIXTURES[0])
|
||||
@mock.patch('nova.image.glance.API.get', return_value=IMAGE_FIXTURES[0])
|
||||
def test_get_image(self, get_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/123')
|
||||
actual_image = self.controller.show(request, '123')
|
||||
@ -152,7 +152,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
matchers.DictMatches(self.expected_image_123))
|
||||
get_mocked.assert_called_once_with(mock.ANY, '123')
|
||||
|
||||
@mock.patch('nova.image.api.API.get', return_value=IMAGE_FIXTURES[1])
|
||||
@mock.patch('nova.image.glance.API.get', return_value=IMAGE_FIXTURES[1])
|
||||
def test_get_image_with_custom_prefix(self, _get_mocked):
|
||||
self.flags(compute_link_prefix='https://zoo.com:42',
|
||||
glance_link_prefix='http://circus.com:34',
|
||||
@ -176,14 +176,14 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
|
||||
self.assertThat(actual_image, matchers.DictMatches(expected_image))
|
||||
|
||||
@mock.patch('nova.image.api.API.get',
|
||||
@mock.patch('nova.image.glance.API.get',
|
||||
side_effect=exception.ImageNotFound(image_id=''))
|
||||
def test_get_image_404(self, _get_mocked):
|
||||
fake_req = self.http_request.blank(self.url_base + 'images/unknown')
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.show, fake_req, 'unknown')
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all', return_value=IMAGE_FIXTURES)
|
||||
@mock.patch('nova.image.glance.API.get_all', return_value=IMAGE_FIXTURES)
|
||||
def test_get_image_details(self, get_all_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/detail')
|
||||
response = self.controller.detail(request)
|
||||
@ -270,14 +270,14 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
|
||||
self.assertThat(expected, matchers.DictListMatches(response_list))
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all')
|
||||
@mock.patch('nova.image.glance.API.get_all')
|
||||
def test_get_image_details_with_limit(self, get_all_mocked):
|
||||
request = self.http_request.blank(self.url_base +
|
||||
'images/detail?limit=2')
|
||||
self.controller.detail(request)
|
||||
get_all_mocked.assert_called_once_with(mock.ANY, limit=2, filters={})
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all')
|
||||
@mock.patch('nova.image.glance.API.get_all')
|
||||
def test_get_image_details_with_limit_and_page_size(self, get_all_mocked):
|
||||
request = self.http_request.blank(
|
||||
self.url_base + 'images/detail?limit=2&page_size=1')
|
||||
@ -285,7 +285,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
get_all_mocked.assert_called_once_with(mock.ANY, limit=2, filters={},
|
||||
page_size=1)
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all')
|
||||
@mock.patch('nova.image.glance.API.get_all')
|
||||
def _detail_request(self, filters, request, get_all_mocked):
|
||||
self.controller.detail(request)
|
||||
get_all_mocked.assert_called_once_with(mock.ANY, filters=filters)
|
||||
@ -344,7 +344,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
request = self.http_request.blank(self.url_base + 'images/detail')
|
||||
self._detail_request(filters, request)
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all', side_effect=exception.Invalid)
|
||||
@mock.patch('nova.image.glance.API.get_all', side_effect=exception.Invalid)
|
||||
def test_image_detail_invalid_marker(self, _get_all_mocked):
|
||||
request = self.http_request.blank(self.url_base + '?marker=invalid')
|
||||
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.detail,
|
||||
@ -360,7 +360,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
def _check_response(self, controller_method, response, expected_code):
|
||||
self.assertEqual(expected_code, controller_method.wsgi_code)
|
||||
|
||||
@mock.patch('nova.image.api.API.delete')
|
||||
@mock.patch('nova.image.glance.API.delete')
|
||||
def test_delete_image(self, delete_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/124')
|
||||
request.method = 'DELETE'
|
||||
@ -369,7 +369,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
self._check_response(delete_method, response, 204)
|
||||
delete_mocked.assert_called_once_with(mock.ANY, '124')
|
||||
|
||||
@mock.patch('nova.image.api.API.delete',
|
||||
@mock.patch('nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotAuthorized(image_id='123'))
|
||||
def test_delete_deleted_image(self, _delete_mocked):
|
||||
# If you try to delete a deleted image, you get back 403 Forbidden.
|
||||
@ -378,7 +378,7 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
self.assertRaises(webob.exc.HTTPForbidden, self.controller.delete,
|
||||
request, '123')
|
||||
|
||||
@mock.patch('nova.image.api.API.delete',
|
||||
@mock.patch('nova.image.glance.API.delete',
|
||||
side_effect=exception.ImageNotFound(image_id='123'))
|
||||
def test_delete_image_not_found(self, _delete_mocked):
|
||||
request = self.http_request.blank(self.url_base + 'images/300')
|
||||
@ -386,7 +386,8 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
self.assertRaises(webob.exc.HTTPNotFound,
|
||||
self.controller.delete, request, '300')
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all', return_value=[IMAGE_FIXTURES[0]])
|
||||
@mock.patch('nova.image.glance.API.get_all',
|
||||
return_value=[IMAGE_FIXTURES[0]])
|
||||
def test_get_image_next_link(self, get_all_mocked):
|
||||
request = self.http_request.blank(
|
||||
self.url_base + 'imagesl?limit=1')
|
||||
@ -398,7 +399,8 @@ class ImagesControllerTestV21(test.NoDBTestCase):
|
||||
self.assertThat({'limit': ['1'], 'marker': [IMAGE_FIXTURES[0]['id']]},
|
||||
matchers.DictMatches(params))
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all', return_value=[IMAGE_FIXTURES[0]])
|
||||
@mock.patch('nova.image.glance.API.get_all',
|
||||
return_value=[IMAGE_FIXTURES[0]])
|
||||
def test_get_image_details_next_link(self, get_all_mocked):
|
||||
request = self.http_request.blank(
|
||||
self.url_base + 'images/detail?limit=1')
|
||||
|
@ -25,7 +25,6 @@ from nova.compute import task_states
|
||||
from nova.compute import vm_states
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova import objects
|
||||
from nova import test
|
||||
@ -85,7 +84,7 @@ class ServerActionsControllerTestV21(test.TestCase):
|
||||
project_id=fakes.FAKE_PROJECT_ID)
|
||||
self.context = self.req.environ['nova.context']
|
||||
|
||||
self.image_api = image.API()
|
||||
self.image_api = glance.API()
|
||||
# Assume that anything that hits the compute API and looks for a
|
||||
# RequestSpec doesn't care about it, since testing logic that deep
|
||||
# should be done in nova.tests.unit.compute.test_compute_api.
|
||||
|
@ -58,7 +58,7 @@ from nova.console import type as ctype
|
||||
from nova import context
|
||||
from nova.db import api as db
|
||||
from nova import exception
|
||||
from nova.image import api as image_api
|
||||
from nova.image import glance as image_api
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.objects import block_device as block_device_obj
|
||||
@ -724,7 +724,7 @@ class ComputeVolumeTestCase(BaseTestCase):
|
||||
else:
|
||||
return {}
|
||||
|
||||
self.stub_out('nova.image.api.API.get', image_api_get)
|
||||
self.stub_out('nova.image.glance.API.get', image_api_get)
|
||||
|
||||
block_device_mapping = [{
|
||||
'boot_index': 0,
|
||||
@ -3558,8 +3558,8 @@ class ComputeTestCase(BaseTestCase,
|
||||
self.assertEqual(state_dict['power_state'],
|
||||
instances[0]['power_state'])
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all')
|
||||
@mock.patch('nova.image.api.API.delete')
|
||||
@mock.patch('nova.image.glance.API.get_all')
|
||||
@mock.patch('nova.image.glance.API.delete')
|
||||
def test_rotate_backups(self, mock_delete, mock_get_all_images):
|
||||
instance = self._create_fake_instance_obj()
|
||||
instance_uuid = instance['uuid']
|
||||
@ -3604,7 +3604,7 @@ class ComputeTestCase(BaseTestCase,
|
||||
rotation=1)
|
||||
self.assertEqual(2, mock_delete.call_count)
|
||||
|
||||
@mock.patch('nova.image.api.API.get_all')
|
||||
@mock.patch('nova.image.glance.API.get_all')
|
||||
def test_rotate_backups_with_image_delete_failed(self,
|
||||
mock_get_all_images):
|
||||
instance = self._create_fake_instance_obj()
|
||||
@ -3664,7 +3664,7 @@ class ComputeTestCase(BaseTestCase,
|
||||
if image_id == uuids.image_id_4:
|
||||
raise exception.ImageDeleteConflict(reason='image is in use')
|
||||
|
||||
with mock.patch.object(nova.image.api.API, 'delete',
|
||||
with mock.patch.object(nova.image.glance.API, 'delete',
|
||||
side_effect=_check_image_id) as mock_delete:
|
||||
# Fake images 4,3,2 should be rotated in sequence
|
||||
self.compute._rotate_backups(self.context, instance=instance,
|
||||
|
@ -41,7 +41,7 @@ import nova.conf
|
||||
from nova import context
|
||||
from nova.db import api as db
|
||||
from nova import exception
|
||||
from nova.image import api as image_api
|
||||
from nova.image import glance as image_api
|
||||
from nova.network import constants
|
||||
from nova.network import model
|
||||
from nova.network import neutron as neutron_api
|
||||
@ -3100,7 +3100,7 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
self.stub_out('nova.objects.BlockDeviceMappingList'
|
||||
'.get_by_instance_uuid',
|
||||
fake_bdm_list_get_by_instance_uuid)
|
||||
self.stub_out('nova.image.api.API.create', fake_image_create)
|
||||
self.stub_out('nova.image.glance.API.create', fake_image_create)
|
||||
self.stub_out('nova.volume.cinder.API.get',
|
||||
lambda self, context, volume_id:
|
||||
{'id': volume_id, 'display_description': ''})
|
||||
|
@ -8956,7 +8956,7 @@ class ComputeManagerMigrationTestCase(test.NoDBTestCase,
|
||||
migration.id = 0
|
||||
|
||||
@mock.patch('nova.compute.utils.notify_about_instance_action')
|
||||
@mock.patch('nova.image.api.API.generate_image_url',
|
||||
@mock.patch('nova.image.glance.API.generate_image_url',
|
||||
return_value='fake-url')
|
||||
@mock.patch.object(objects.Migration, 'get_by_id',
|
||||
return_value=migration)
|
||||
|
@ -42,7 +42,7 @@ from nova.db import api as db
|
||||
from nova.db.sqlalchemy import api as db_api
|
||||
from nova.db.sqlalchemy import api_models
|
||||
from nova import exception as exc
|
||||
from nova.image import api as image_api
|
||||
from nova.image import glance as image_api
|
||||
from nova import objects
|
||||
from nova.objects import base as obj_base
|
||||
from nova.objects import block_device as block_device_obj
|
||||
|
@ -86,7 +86,7 @@ class TestSendInstanceUpdateNotification(test.NoDBTestCase):
|
||||
mock.sentinel.ctxt, mock.sentinel.instance, None,
|
||||
populate_image_ref_url=True)
|
||||
|
||||
@mock.patch('nova.image.api.API.generate_image_url',
|
||||
@mock.patch('nova.image.glance.API.generate_image_url',
|
||||
side_effect=ks_exc.EndpointNotFound)
|
||||
def test_info_from_instance_image_api_endpoint_not_found_no_token(
|
||||
self, mock_gen_image_url):
|
||||
@ -105,7 +105,7 @@ class TestSendInstanceUpdateNotification(test.NoDBTestCase):
|
||||
self.assertEqual(instance.image_ref, payload['image_ref_url'])
|
||||
mock_gen_image_url.assert_called_once_with(instance.image_ref, ctxt)
|
||||
|
||||
@mock.patch('nova.image.api.API.generate_image_url',
|
||||
@mock.patch('nova.image.glance.API.generate_image_url',
|
||||
side_effect=ks_exc.EndpointNotFound)
|
||||
def test_info_from_instance_image_api_endpoint_not_found_with_token(
|
||||
self, mock_gen_image_url):
|
||||
@ -121,7 +121,7 @@ class TestSendInstanceUpdateNotification(test.NoDBTestCase):
|
||||
populate_image_ref_url=True)
|
||||
mock_gen_image_url.assert_called_once_with(instance.image_ref, ctxt)
|
||||
|
||||
@mock.patch('nova.image.api.API.generate_image_url')
|
||||
@mock.patch('nova.image.glance.API.generate_image_url')
|
||||
def test_info_from_instance_not_call_generate_image_url(
|
||||
self, mock_gen_image_url):
|
||||
ctxt = nova_context.get_admin_context()
|
||||
|
@ -54,7 +54,7 @@ class TestProfiler(test.NoDBTestCase):
|
||||
'nova.conductor.manager.ConductorManager',
|
||||
'nova.conductor.rpcapi.ComputeTaskAPI',
|
||||
'nova.conductor.rpcapi.ConductorAPI',
|
||||
'nova.image.api.API',
|
||||
'nova.image.glance.API',
|
||||
'nova.network.neutron.ClientWrapper',
|
||||
'nova.scheduler.manager.SchedulerManager',
|
||||
'nova.scheduler.rpcapi.SchedulerAPI',
|
||||
|
@ -171,7 +171,7 @@ class TestLocalDisk(test.NoDBTestCase):
|
||||
mock_upload_image.assert_called_once_with(
|
||||
'context', 'instance', mock_image_meta)
|
||||
|
||||
@mock.patch('nova.image.api.API.download')
|
||||
@mock.patch('nova.image.glance.API.download')
|
||||
@mock.patch('nova.virt.powervm.disk.driver.IterableToFileAdapter')
|
||||
@mock.patch('pypowervm.tasks.storage.upload_new_vdisk')
|
||||
@mock.patch('nova.virt.powervm.disk.driver.DiskAdapter._get_disk_name')
|
||||
|
@ -164,7 +164,7 @@ class TestSSPDiskAdapter(test.NoDBTestCase):
|
||||
new_callable=mock.PropertyMock)
|
||||
@mock.patch('pypowervm.util.sanitize_file_name_for_api', autospec=True)
|
||||
@mock.patch('pypowervm.tasks.storage.crt_lu', autospec=True)
|
||||
@mock.patch('nova.image.api.API.download')
|
||||
@mock.patch('nova.image.glance.API.download')
|
||||
@mock.patch('nova.virt.powervm.disk.driver.IterableToFileAdapter',
|
||||
autospec=True)
|
||||
def test_create_disk_from_image(self, mock_it2f, mock_dl, mock_crt_lu,
|
||||
|
@ -82,7 +82,7 @@ class TestPowerVMDriver(test.NoDBTestCase):
|
||||
self.assertTrue(self.drv.capabilities['supports_extend_volume'])
|
||||
self.assertFalse(self.drv.capabilities['supports_multiattach'])
|
||||
|
||||
@mock.patch('nova.image.API')
|
||||
@mock.patch('nova.image.glance.API')
|
||||
@mock.patch('pypowervm.tasks.storage.ComprehensiveScrub', autospec=True)
|
||||
@mock.patch('oslo_utils.importutils.import_object_ns', autospec=True)
|
||||
@mock.patch('pypowervm.wrappers.managed_system.System', autospec=True)
|
||||
|
@ -25,7 +25,7 @@ from nova.virt.powervm import image
|
||||
class TestImage(test.TestCase):
|
||||
|
||||
@mock.patch('nova.utils.temporary_chown', autospec=True)
|
||||
@mock.patch('nova.image.api.API', autospec=True)
|
||||
@mock.patch('nova.image.glance.API', autospec=True)
|
||||
def test_stream_blockdev_to_glance(self, mock_api, mock_chown):
|
||||
mock_open = mock.mock_open()
|
||||
with mock.patch.object(six.moves.builtins, 'open', new=mock_open):
|
||||
@ -36,7 +36,7 @@ class TestImage(test.TestCase):
|
||||
mock_api.update.assert_called_with('context', 'image_id', 'metadata',
|
||||
mock_open.return_value)
|
||||
|
||||
@mock.patch('nova.image.api.API', autospec=True)
|
||||
@mock.patch('nova.image.glance.API', autospec=True)
|
||||
def test_generate_snapshot_metadata(self, mock_api):
|
||||
mock_api.get.return_value = {'name': 'image_name'}
|
||||
mock_instance = mock.Mock()
|
||||
|
@ -383,7 +383,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
||||
def test_get_datacenter_ref_and_name_with_no_datastore(self):
|
||||
self._test_get_datacenter_ref_and_name()
|
||||
|
||||
@mock.patch('nova.image.api.API.get')
|
||||
@mock.patch('nova.image.glance.API.get')
|
||||
@mock.patch.object(vm_util, 'power_off_instance')
|
||||
@mock.patch.object(ds_util, 'disk_copy')
|
||||
@mock.patch.object(vm_util, 'get_vm_ref', return_value='fake-ref')
|
||||
@ -1138,7 +1138,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
||||
mock_attach_cdrom_to_vm.assert_called_once_with(
|
||||
vm_ref, self._instance, self._ds.ref, str(upload_iso_path))
|
||||
|
||||
@mock.patch('nova.image.api.API.get')
|
||||
@mock.patch('nova.image.glance.API.get')
|
||||
@mock.patch.object(vmops.LOG, 'debug')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_fetch_image_if_missing')
|
||||
@mock.patch.object(vmops.VMwareVMOps, '_get_vm_config_info')
|
||||
@ -1650,7 +1650,7 @@ class VMwareVMOpsTestCase(test.NoDBTestCase):
|
||||
mock.patch.object(uuidutils, 'generate_uuid',
|
||||
return_value='tmp-uuid'),
|
||||
mock.patch.object(images, 'fetch_image'),
|
||||
mock.patch('nova.image.api.API.get'),
|
||||
mock.patch('nova.image.glance.API.get'),
|
||||
mock.patch.object(vutil, 'get_inventory_path',
|
||||
return_value=self._dc_info.name),
|
||||
mock.patch.object(self._vmops, '_get_extra_specs',
|
||||
|
@ -20,7 +20,7 @@ from os_xenapi.client import image
|
||||
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova.image.api import API as image_api
|
||||
from nova.image.glance import API as image_api
|
||||
from nova.tests.unit.virt.xenapi import stubs
|
||||
from nova.virt.xenapi.image import utils
|
||||
from nova.virt.xenapi.image import vdi_stream
|
||||
|
@ -32,13 +32,13 @@ from nova.compute import utils as compute_utils
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
import nova.privsep.qemu
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
QEMU_IMG_LIMITS = processutils.ProcessLimits(
|
||||
cpu_time=30,
|
||||
|
@ -87,7 +87,7 @@ from nova import crypto
|
||||
from nova.db import constants as db_const
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.network import model as network_model
|
||||
from nova import objects
|
||||
from nova.objects import diagnostics as diagnostics_obj
|
||||
@ -379,7 +379,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
self.disk_cachemodes[disk_type] = cache_mode
|
||||
|
||||
self._volume_api = cinder.API()
|
||||
self._image_api = image.API()
|
||||
self._image_api = glance.API()
|
||||
|
||||
# The default choice for the sysinfo_serial config option is "unique"
|
||||
# which does not have a special function since the value is just the
|
||||
|
@ -34,7 +34,7 @@ import six
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
import nova.privsep.libvirt
|
||||
import nova.privsep.path
|
||||
from nova import utils
|
||||
@ -50,7 +50,7 @@ from nova.virt.libvirt import utils as libvirt_utils
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
|
||||
# NOTE(neiljerram): Don't worry if this fails. This sometimes happens, with
|
||||
|
@ -24,13 +24,13 @@ from pypowervm.wrappers import virtual_io_server as pvm_vios
|
||||
|
||||
from nova import conf
|
||||
from nova import exception
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.virt.powervm.disk import driver as disk_dvr
|
||||
from nova.virt.powervm import vm
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = conf.CONF
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
|
||||
class LocalStorage(disk_dvr.DiskAdapter):
|
||||
|
@ -26,13 +26,13 @@ import pypowervm.wrappers.cluster as pvm_clust
|
||||
import pypowervm.wrappers.storage as pvm_stg
|
||||
|
||||
from nova import exception
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.virt.powervm.disk import driver as disk_drv
|
||||
from nova.virt.powervm import vm
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
|
||||
class SSPDiskAdapter(disk_drv.DiskAdapter):
|
||||
|
@ -34,7 +34,7 @@ from nova import conf as cfg
|
||||
from nova.console import type as console_type
|
||||
from nova import exception as exc
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.virt import configdrive
|
||||
from nova.virt import driver
|
||||
from nova.virt.powervm import host as pvm_host
|
||||
@ -118,7 +118,7 @@ class PowerVMDriver(driver.ComputeDriver):
|
||||
self.disk_dvr = importutils.import_object_ns(
|
||||
DISK_ADPT_NS, DISK_ADPT_MAPPINGS[CONF.powervm.disk_driver.lower()],
|
||||
self.adapter, self.host_wrapper.uuid)
|
||||
self.image_api = image.API()
|
||||
self.image_api = glance.API()
|
||||
|
||||
LOG.info("The PowerVM compute driver has been initialized.")
|
||||
|
||||
|
@ -32,7 +32,7 @@ from oslo_vmware import rw_handles
|
||||
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova.objects import fields
|
||||
from nova.virt.vmwareapi import constants
|
||||
from nova.virt.vmwareapi import vm_util
|
||||
@ -45,7 +45,7 @@ from nova.virt.vmwareapi import vm_util
|
||||
CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
QUEUE_BUFFER_SIZE = 10
|
||||
NFC_LEASE_UPDATE_PERIOD = 60 # update NFC lease every 60sec.
|
||||
|
@ -19,11 +19,11 @@ import tarfile
|
||||
from oslo_utils import importutils
|
||||
|
||||
from nova import exception
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
|
||||
_VDI_FORMAT_RAW = 1
|
||||
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
IMAGE_HANDLERS = {'direct_vhd': 'glance.GlanceStore',
|
||||
'vdi_local_dev': 'vdi_through_dev.VdiThroughDevStore',
|
||||
'vdi_remote_stream': 'vdi_stream.VdiStreamStore'}
|
||||
|
@ -22,7 +22,7 @@ from oslo_log import log as logging
|
||||
|
||||
import nova.conf
|
||||
from nova import exception
|
||||
from nova import image
|
||||
from nova.image import glance
|
||||
from nova import utils as nova_utils
|
||||
from nova.virt.xenapi.image import utils
|
||||
from nova.virt.xenapi import vm_utils
|
||||
@ -30,7 +30,7 @@ from nova.virt.xenapi import vm_utils
|
||||
CONF = nova.conf.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
IMAGE_API = image.API()
|
||||
IMAGE_API = glance.API()
|
||||
|
||||
|
||||
class VdiStreamStore(object):
|
||||
|
Loading…
x
Reference in New Issue
Block a user