Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fixes LP Bug#861650 - Glance client deps
This patch addresses the dependency proliferation in
the glance client stuff. It removes references to modules
that contain non-client-necessary libraries (like
eventlet, xattr, sqlalchemy-migrate and sqlalchemy)
by restructuring the modules slightly.

Note that the additional httplib2 dependency is because
that is used in the authentication strategy stuff in
glance.common.auth. This could be rewritten to use httplib
instead, further reducing the dependencies of the client lib.

IMPORTANT NOTE: This patch changes the default entrypoint
for the Images API router application, and therefore this
should be merged along with the packaging changes in this
branch:

https://code.launchpad.net/~jaypipes/glance/ubuntu/+merge/82318

Change-Id: I5dbc8584fb77e3e011fb6ff3532f792f5103e242
  • Loading branch information
jaypipes committed Nov 30, 2011
1 parent 6bf61e8 commit 1ab63ff
Show file tree
Hide file tree
Showing 17 changed files with 247 additions and 291 deletions.
2 changes: 1 addition & 1 deletion bin/glance
Expand Up @@ -40,8 +40,8 @@ if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):

gettext.install('glance', unicode=1)

from glance import client as glance_client
from glance import version
from glance import client as glance_client
from glance.common import exception
from glance.common import utils

Expand Down
2 changes: 1 addition & 1 deletion etc/glance-api.conf
Expand Up @@ -214,7 +214,7 @@ pipeline = versionnegotiation context apiv1app
# pipeline = versionnegotiation authtoken auth-context cachemanage apiv1app

[app:apiv1app]
paste.app_factory = glance.api.v1:app_factory
paste.app_factory = glance.api.v1.router:app_factory

[filter:versionnegotiation]
paste.filter_factory = glance.api.middleware.version_negotiation:filter_factory
Expand Down
47 changes: 0 additions & 47 deletions glance/api/__init__.py
Expand Up @@ -14,50 +14,3 @@
# 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 logging
import webob.exc

from glance import registry
from glance.common import exception


logger = logging.getLogger('glance.api')


class BaseController(object):
def get_image_meta_or_404(self, request, image_id):
"""
Grabs the image metadata for an image with a supplied
identifier or raises an HTTPNotFound (404) response
:param request: The WSGI/Webob Request object
:param image_id: The opaque image identifier
:raises HTTPNotFound if image does not exist
"""
context = request.context
try:
return registry.get_image_metadata(context, image_id)
except exception.NotFound:
msg = _("Image with identifier %s not found") % image_id
logger.debug(msg)
raise webob.exc.HTTPNotFound(
msg, request=request, content_type='text/plain')
except exception.NotAuthorized:
msg = _("Unauthorized image access")
logger.debug(msg)
raise webob.exc.HTTPForbidden(msg, request=request,
content_type='text/plain')

def get_active_image_meta_or_404(self, request, image_id):
"""
Same as get_image_meta_or_404 except that it will raise a 404 if the
image isn't 'active'.
"""
image = self.get_image_meta_or_404(request, image_id)
if image['status'] != 'active':
msg = _("Image %s is not active") % image_id
logger.debug(msg)
raise webob.exc.HTTPNotFound(
msg, request=request, content_type='text/plain')
return image
4 changes: 2 additions & 2 deletions glance/api/cached_images.py
Expand Up @@ -25,14 +25,14 @@

from glance.common import exception
from glance.common import wsgi
from glance import api
from glance.api.v1 import controller
from glance import image_cache
from glance import registry

logger = logging.getLogger(__name__)


class Controller(api.BaseController):
class Controller(controller.BaseController):
"""
A controller for managing cached images.
"""
Expand Down
51 changes: 4 additions & 47 deletions glance/api/v1/__init__.py
Expand Up @@ -15,51 +15,8 @@
# License for the specific language governing permissions and limitations
# under the License.

import logging
SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
'min_ram', 'min_disk', 'size_min', 'size_max',
'is_public', 'changes-since']

import routes

from glance.api.v1 import images
from glance.api.v1 import members
from glance.common import wsgi

logger = logging.getLogger('glance.api.v1')


class API(wsgi.Router):

"""WSGI router for Glance v1 API requests."""

def __init__(self, options):
self.options = options
mapper = routes.Mapper()

images_resource = images.create_resource(options)

mapper.resource("image", "images", controller=images_resource,
collection={'detail': 'GET'})
mapper.connect("/", controller=images_resource, action="index")
mapper.connect("/images/{id}", controller=images_resource,
action="meta", conditions=dict(method=["HEAD"]))

members_resource = members.create_resource(options)

mapper.resource("member", "members", controller=members_resource,
parent_resource=dict(member_name='image',
collection_name='images'))
mapper.connect("/shared-images/{id}",
controller=members_resource,
action="index_shared_images")
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="update_all",
conditions=dict(method=["PUT"]))

super(API, self).__init__(mapper)


def app_factory(global_conf, **local_conf):
"""paste.deploy app factory for creating Glance API server apps"""
conf = global_conf.copy()
conf.update(local_conf)
return API(conf)
SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')
64 changes: 64 additions & 0 deletions glance/api/v1/controller.py
@@ -0,0 +1,64 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2011 OpenStack LLC.
# 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 logging

import webob.exc

from glance import registry
from glance.common import exception

logger = logging.getLogger(__name__)


class BaseController(object):
def get_image_meta_or_404(self, request, image_id):
"""
Grabs the image metadata for an image with a supplied
identifier or raises an HTTPNotFound (404) response
:param request: The WSGI/Webob Request object
:param image_id: The opaque image identifier
:raises HTTPNotFound if image does not exist
"""
context = request.context
try:
return registry.get_image_metadata(context, image_id)
except exception.NotFound:
msg = _("Image with identifier %s not found") % image_id
logger.debug(msg)
raise webob.exc.HTTPNotFound(
msg, request=request, content_type='text/plain')
except exception.NotAuthorized:
msg = _("Unauthorized image access")
logger.debug(msg)
raise webob.exc.HTTPForbidden(msg, request=request,
content_type='text/plain')

def get_active_image_meta_or_404(self, request, image_id):
"""
Same as get_image_meta_or_404 except that it will raise a 404 if the
image isn't 'active'.
"""
image = self.get_image_meta_or_404(request, image_id)
if image['status'] != 'active':
msg = _("Image %s is not active") % image_id
logger.debug(msg)
raise webob.exc.HTTPNotFound(
msg, request=request, content_type='text/plain')
return image
20 changes: 9 additions & 11 deletions glance/api/v1/images.py
Expand Up @@ -31,11 +31,13 @@
HTTPNoContent,
HTTPUnauthorized)

from glance import api
import glance.api.v1
from glance.api.v1 import controller
from glance import image_cache
from glance.common import exception
from glance.common import notifier
from glance.common import wsgi
from glance.common import utils
import glance.store
import glance.store.filesystem
import glance.store.http
Expand All @@ -50,16 +52,12 @@
from glance import registry


logger = logging.getLogger('glance.api.v1.images')
logger = logging.getLogger(__name__)
SUPPORTED_PARAMS = glance.api.v1.SUPPORTED_PARAMS
SUPPORTED_FILTERS = glance.api.v1.SUPPORTED_FILTERS

SUPPORTED_FILTERS = ['name', 'status', 'container_format', 'disk_format',
'min_ram', 'min_disk', 'size_min', 'size_max',
'is_public', 'changes-since']

SUPPORTED_PARAMS = ('limit', 'marker', 'sort_key', 'sort_dir')


class Controller(api.BaseController):
class Controller(controller.BaseController):
"""
WSGI controller for images resource in Glance v1 API
Expand Down Expand Up @@ -596,7 +594,7 @@ class ImageDeserializer(wsgi.JSONRequestDeserializer):

def _deserialize(self, request):
result = {}
result['image_meta'] = wsgi.get_image_meta_from_headers(request)
result['image_meta'] = utils.get_image_meta_from_headers(request)
data = request.body_file if self.has_body(request) else None
result['image_data'] = data
return result
Expand Down Expand Up @@ -630,7 +628,7 @@ def _inject_image_meta_headers(self, response, image_meta):
:param response: The Webob Response object
:param image_meta: Mapping of image metadata
"""
headers = wsgi.image_meta_to_http_headers(image_meta)
headers = utils.image_meta_to_http_headers(image_meta)

for k, v in headers.items():
response.headers[k] = v
Expand Down
65 changes: 65 additions & 0 deletions glance/api/v1/router.py
@@ -0,0 +1,65 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright 2011 OpenStack LLC.
# 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 logging

import routes

from glance.api.v1 import images
from glance.api.v1 import members
from glance.common import wsgi

logger = logging.getLogger(__name__)


class API(wsgi.Router):

"""WSGI router for Glance v1 API requests."""

def __init__(self, options):
self.options = options
mapper = routes.Mapper()

images_resource = images.create_resource(options)

mapper.resource("image", "images", controller=images_resource,
collection={'detail': 'GET'})
mapper.connect("/", controller=images_resource, action="index")
mapper.connect("/images/{id}", controller=images_resource,
action="meta", conditions=dict(method=["HEAD"]))

members_resource = members.create_resource(options)

mapper.resource("member", "members", controller=members_resource,
parent_resource=dict(member_name='image',
collection_name='images'))
mapper.connect("/shared-images/{id}",
controller=members_resource,
action="index_shared_images")
mapper.connect("/images/{image_id}/members",
controller=members_resource,
action="update_all",
conditions=dict(method=["PUT"]))

super(API, self).__init__(mapper)


def app_factory(global_conf, **local_conf):
"""paste.deploy app factory for creating Glance API server apps"""
conf = global_conf.copy()
conf.update(local_conf)
return API(conf)

0 comments on commit 1ab63ff

Please sign in to comment.