diff options
| author | Brian Waldon <brian.waldon@rackspace.com> | 2011-11-11 13:26:13 -0500 |
|---|---|---|
| committer | Brian Waldon <brian.waldon@rackspace.com> | 2011-11-17 10:09:15 -0800 |
| commit | de635fc882caebd5d5c9701e755a7174e37a05c5 (patch) | |
| tree | 7f7414caef497db6b0c7710569391f52c246b8cc /nova/api | |
| parent | f14ec8a9e2ef9d7869e9834bd054e9c0e271ec31 (diff) | |
| download | nova-de635fc882caebd5d5c9701e755a7174e37a05c5.tar.gz nova-de635fc882caebd5d5c9701e755a7174e37a05c5.tar.xz nova-de635fc882caebd5d5c9701e755a7174e37a05c5.zip | |
Creating new v2 namespace in nova.api.openstack
Related to blueprint separate-nova-adminapi
Change-Id: Ida35372b7263c4a4efdafd35faa1325c4436459b
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/openstack/__init__.py | 187 | ||||
| -rw-r--r-- | nova/api/openstack/faults.py | 116 | ||||
| -rw-r--r-- | nova/api/openstack/v2/__init__.py | 186 | ||||
| -rw-r--r-- | nova/api/openstack/v2/accounts.py (renamed from nova/api/openstack/accounts.py) | 10 | ||||
| -rw-r--r-- | nova/api/openstack/v2/auth.py (renamed from nova/api/openstack/auth.py) | 30 | ||||
| -rw-r--r-- | nova/api/openstack/v2/consoles.py (renamed from nova/api/openstack/consoles.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/__init__.py (renamed from nova/api/openstack/contrib/__init__.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/admin_actions.py (renamed from nova/api/openstack/contrib/admin_actions.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/createserverext.py (renamed from nova/api/openstack/contrib/createserverext.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/deferred_delete.py (renamed from nova/api/openstack/contrib/deferred_delete.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/disk_config.py (renamed from nova/api/openstack/contrib/disk_config.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/extended_status.py (renamed from nova/api/openstack/contrib/extended_status.py) | 7 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/flavorextradata.py (renamed from nova/api/openstack/contrib/flavorextradata.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/flavorextraspecs.py (renamed from nova/api/openstack/contrib/flavorextraspecs.py) | 3 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/floating_ips.py (renamed from nova/api/openstack/contrib/floating_ips.py) | 5 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/hosts.py (renamed from nova/api/openstack/contrib/hosts.py) | 7 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/keypairs.py (renamed from nova/api/openstack/contrib/keypairs.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/multinic.py (renamed from nova/api/openstack/contrib/multinic.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/quotas.py (renamed from nova/api/openstack/contrib/quotas.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/rescue.py (renamed from nova/api/openstack/contrib/rescue.py) | 5 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/security_groups.py (renamed from nova/api/openstack/contrib/security_groups.py) | 14 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/simple_tenant_usage.py (renamed from nova/api/openstack/contrib/simple_tenant_usage.py) | 13 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/virtual_interfaces.py (renamed from nova/api/openstack/contrib/virtual_interfaces.py) | 8 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/virtual_storage_arrays.py (renamed from nova/api/openstack/contrib/virtual_storage_arrays.py) | 20 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/volumes.py (renamed from nova/api/openstack/contrib/volumes.py) | 8 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/volumetypes.py (renamed from nova/api/openstack/contrib/volumetypes.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/zones.py (renamed from nova/api/openstack/contrib/zones.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/extensions.py (renamed from nova/api/openstack/extensions.py) | 12 | ||||
| -rw-r--r-- | nova/api/openstack/v2/flavors.py (renamed from nova/api/openstack/flavors.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/image_metadata.py (renamed from nova/api/openstack/image_metadata.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/v2/images.py (renamed from nova/api/openstack/images.py) | 12 | ||||
| -rw-r--r-- | nova/api/openstack/v2/ips.py (renamed from nova/api/openstack/ips.py) | 5 | ||||
| -rw-r--r-- | nova/api/openstack/v2/limits.py (renamed from nova/api/openstack/limits.py) | 18 | ||||
| -rw-r--r-- | nova/api/openstack/v2/ratelimiting/__init__.py (renamed from nova/api/openstack/ratelimiting/__init__.py) | 5 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/atom-link.rng (renamed from nova/api/openstack/schemas/atom-link.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/atom.rng (renamed from nova/api/openstack/schemas/atom.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/addresses.rng (renamed from nova/api/openstack/schemas/v1.1/addresses.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/extension.rng (renamed from nova/api/openstack/schemas/v1.1/extension.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/extensions.rng (renamed from nova/api/openstack/schemas/v1.1/extensions.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/flavor.rng (renamed from nova/api/openstack/schemas/v1.1/flavor.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/flavors.rng (renamed from nova/api/openstack/schemas/v1.1/flavors.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/flavors_index.rng (renamed from nova/api/openstack/schemas/v1.1/flavors_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/image.rng (renamed from nova/api/openstack/schemas/v1.1/image.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/images.rng (renamed from nova/api/openstack/schemas/v1.1/images.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/images_index.rng (renamed from nova/api/openstack/schemas/v1.1/images_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/limits.rng (renamed from nova/api/openstack/schemas/v1.1/limits.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/metadata.rng (renamed from nova/api/openstack/schemas/v1.1/metadata.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/server.rng (renamed from nova/api/openstack/schemas/v1.1/server.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/servers.rng (renamed from nova/api/openstack/schemas/v1.1/servers.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/servers_index.rng (renamed from nova/api/openstack/schemas/v1.1/servers_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/version.rng (renamed from nova/api/openstack/schemas/v1.1/version.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/schemas/v1.1/versions.rng (renamed from nova/api/openstack/schemas/v1.1/versions.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/server_metadata.py (renamed from nova/api/openstack/server_metadata.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/servers.py (renamed from nova/api/openstack/servers.py) | 13 | ||||
| -rw-r--r-- | nova/api/openstack/v2/urlmap.py (renamed from nova/api/openstack/urlmap.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/users.py (renamed from nova/api/openstack/users.py) | 8 | ||||
| -rw-r--r-- | nova/api/openstack/v2/versions.py (renamed from nova/api/openstack/versions.py) | 7 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/__init__.py (renamed from nova/api/openstack/views/__init__.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/addresses.py (renamed from nova/api/openstack/views/addresses.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/flavors.py (renamed from nova/api/openstack/views/flavors.py) | 1 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/images.py (renamed from nova/api/openstack/views/images.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/limits.py (renamed from nova/api/openstack/views/limits.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/servers.py (renamed from nova/api/openstack/views/servers.py) | 11 | ||||
| -rw-r--r-- | nova/api/openstack/v2/views/versions.py (renamed from nova/api/openstack/views/versions.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/v2/zones.py (renamed from nova/api/openstack/zones.py) | 14 | ||||
| -rw-r--r-- | nova/api/openstack/wsgi.py | 107 | ||||
| -rw-r--r-- | nova/api/openstack/xmlutil.py | 4 |
67 files changed, 430 insertions, 472 deletions
diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index 07911221d..e69de29bb 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -1,187 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# 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. - -""" -WSGI middleware for OpenStack API controllers. -""" - -import routes -import webob.dec -import webob.exc - -from nova.api.openstack import accounts -from nova.api.openstack import faults -from nova.api.openstack import consoles -from nova.api.openstack import flavors -from nova.api.openstack import images -from nova.api.openstack import image_metadata -from nova.api.openstack import ips -from nova.api.openstack import limits -from nova.api.openstack import servers -from nova.api.openstack import server_metadata -from nova.api.openstack import users -from nova.api.openstack import versions -from nova.api.openstack import wsgi -from nova.api.openstack import zones -from nova import flags -from nova import log as logging -from nova import wsgi as base_wsgi - - -LOG = logging.getLogger('nova.api.openstack') -FLAGS = flags.FLAGS -flags.DEFINE_bool('allow_admin_api', - False, - 'When True, this API service will accept admin operations.') -flags.DEFINE_bool('allow_instance_snapshots', - True, - 'When True, this API service will permit instance snapshot operations.') - - -class FaultWrapper(base_wsgi.Middleware): - """Calls down the middleware stack, making exceptions into faults.""" - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - try: - return req.get_response(self.application) - except Exception as ex: - LOG.exception(_("Caught error: %s"), unicode(ex)) - exc = webob.exc.HTTPInternalServerError() - return faults.Fault(exc) - - -class APIMapper(routes.Mapper): - def routematch(self, url=None, environ=None): - if url is "": - result = self._match("", environ) - return result[0], result[1] - return routes.Mapper.routematch(self, url, environ) - - -class ProjectMapper(APIMapper): - - def resource(self, member_name, collection_name, **kwargs): - if not ('parent_resource' in kwargs): - kwargs['path_prefix'] = '{project_id}/' - else: - parent_resource = kwargs['parent_resource'] - p_collection = parent_resource['collection_name'] - p_member = parent_resource['member_name'] - kwargs['path_prefix'] = '{project_id}/%s/:%s_id' % (p_collection, - p_member) - routes.Mapper.resource(self, member_name, - collection_name, - **kwargs) - - -class APIRouter(base_wsgi.Router): - """ - Routes requests on the OpenStack API to the appropriate controller - and method. - """ - - @classmethod - def factory(cls, global_config, **local_config): - """Simple paste factory, :class:`nova.wsgi.Router` doesn't have one""" - return cls() - - def __init__(self, ext_mgr=None): - self.server_members = {} - mapper = ProjectMapper() - self._setup_routes(mapper) - super(APIRouter, self).__init__(mapper) - - def _setup_routes(self, mapper): - server_members = self.server_members - server_members['action'] = 'POST' - if FLAGS.allow_admin_api: - LOG.debug(_("Including admin operations in API.")) - - server_members['diagnostics'] = 'GET' - server_members['actions'] = 'GET' - - mapper.resource("user", "users", - controller=users.create_resource(), - collection={'detail': 'GET'}) - - mapper.resource("account", "accounts", - controller=accounts.create_resource(), - collection={'detail': 'GET'}) - - mapper.resource("zone", "zones", - controller=zones.create_resource(), - collection={'detail': 'GET', - 'info': 'GET', - 'select': 'POST'}) - - mapper.connect("versions", "/", - controller=versions.create_resource(), - action='show') - - mapper.redirect("", "/") - - mapper.resource("console", "consoles", - controller=consoles.create_resource(), - parent_resource=dict(member_name='server', - collection_name='servers')) - - mapper.resource("server", "servers", - controller=servers.create_resource(), - collection={'detail': 'GET'}, - member=self.server_members) - - mapper.resource("ip", "ips", controller=ips.create_resource(), - parent_resource=dict(member_name='server', - collection_name='servers')) - - mapper.resource("image", "images", - controller=images.create_resource(), - collection={'detail': 'GET'}) - - mapper.resource("limit", "limits", - controller=limits.create_resource()) - - mapper.resource("flavor", "flavors", - controller=flavors.create_resource(), - collection={'detail': 'GET'}) - - image_metadata_controller = image_metadata.create_resource() - - mapper.resource("image_meta", "metadata", - controller=image_metadata_controller, - parent_resource=dict(member_name='image', - collection_name='images')) - - mapper.connect("metadata", "/{project_id}/images/{image_id}/metadata", - controller=image_metadata_controller, - action='update_all', - conditions={"method": ['PUT']}) - - server_metadata_controller = server_metadata.create_resource() - - mapper.resource("server_meta", "metadata", - controller=server_metadata_controller, - parent_resource=dict(member_name='server', - collection_name='servers')) - - mapper.connect("metadata", - "/{project_id}/servers/{server_id}/metadata", - controller=server_metadata_controller, - action='update_all', - conditions={"method": ['PUT']}) diff --git a/nova/api/openstack/faults.py b/nova/api/openstack/faults.py deleted file mode 100644 index 83381d755..000000000 --- a/nova/api/openstack/faults.py +++ /dev/null @@ -1,116 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 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 webob.dec -import webob.exc - -from nova.api.openstack import common -from nova.api.openstack import wsgi - - -class Fault(webob.exc.HTTPException): - """Wrap webob.exc.HTTPException to provide API friendly response.""" - - _fault_names = { - 400: "badRequest", - 401: "unauthorized", - 403: "resizeNotAllowed", - 404: "itemNotFound", - 405: "badMethod", - 409: "inProgress", - 413: "overLimit", - 415: "badMediaType", - 501: "notImplemented", - 503: "serviceUnavailable"} - - def __init__(self, exception): - """Create a Fault for the given webob.exc.exception.""" - self.wrapped_exc = exception - self.status_int = exception.status_int - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, req): - """Generate a WSGI response based on the exception passed to ctor.""" - # Replace the body with fault details. - code = self.wrapped_exc.status_int - fault_name = self._fault_names.get(code, "cloudServersFault") - fault_data = { - fault_name: { - 'code': code, - 'message': self.wrapped_exc.explanation}} - if code == 413: - retry = self.wrapped_exc.headers['Retry-After'] - fault_data[fault_name]['retryAfter'] = retry - - # 'code' is an attribute on the fault tag itself - metadata = {'attributes': {fault_name: 'code'}} - - xml_serializer = wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11) - - content_type = req.best_match_content_type() - serializer = { - 'application/xml': xml_serializer, - 'application/json': wsgi.JSONDictSerializer(), - }[content_type] - - self.wrapped_exc.body = serializer.serialize(fault_data) - self.wrapped_exc.content_type = content_type - - return self.wrapped_exc - - def __str__(self): - return self.wrapped_exc.__str__() - - -class OverLimitFault(webob.exc.HTTPException): - """ - Rate-limited request response. - """ - - def __init__(self, message, details, retry_time): - """ - Initialize new `OverLimitFault` with relevant information. - """ - self.wrapped_exc = webob.exc.HTTPRequestEntityTooLarge() - self.content = { - "overLimitFault": { - "code": self.wrapped_exc.status_int, - "message": message, - "details": details, - }, - } - - @webob.dec.wsgify(RequestClass=wsgi.Request) - def __call__(self, request): - """ - Return the wrapped exception with a serialized body conforming to our - error format. - """ - content_type = request.best_match_content_type() - metadata = {"attributes": {"overLimitFault": "code"}} - - xml_serializer = wsgi.XMLDictSerializer(metadata, wsgi.XMLNS_V11) - serializer = { - 'application/xml': xml_serializer, - 'application/json': wsgi.JSONDictSerializer(), - }[content_type] - - content = serializer.serialize(self.content) - self.wrapped_exc.body = content - - return self.wrapped_exc diff --git a/nova/api/openstack/v2/__init__.py b/nova/api/openstack/v2/__init__.py new file mode 100644 index 000000000..1ea2ba250 --- /dev/null +++ b/nova/api/openstack/v2/__init__.py @@ -0,0 +1,186 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# 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. + +""" +WSGI middleware for OpenStack API controllers. +""" + +import routes +import webob.dec +import webob.exc + +from nova.api.openstack.v2 import accounts +from nova.api.openstack.v2 import consoles +from nova.api.openstack.v2 import flavors +from nova.api.openstack.v2 import images +from nova.api.openstack.v2 import image_metadata +from nova.api.openstack.v2 import ips +from nova.api.openstack.v2 import limits +from nova.api.openstack.v2 import servers +from nova.api.openstack.v2 import server_metadata +from nova.api.openstack.v2 import users +from nova.api.openstack.v2 import versions +from nova.api.openstack.v2 import zones +from nova.api.openstack import wsgi +from nova import flags +from nova import log as logging +from nova import wsgi as base_wsgi + + +LOG = logging.getLogger('nova.api.openstack.v2') +FLAGS = flags.FLAGS +flags.DEFINE_bool('allow_admin_api', + False, + 'When True, this API service will accept admin operations.') +flags.DEFINE_bool('allow_instance_snapshots', + True, + 'When True, this API service will permit instance snapshot operations.') + + +class FaultWrapper(base_wsgi.Middleware): + """Calls down the middleware stack, making exceptions into faults.""" + + @webob.dec.wsgify(RequestClass=wsgi.Request) + def __call__(self, req): + try: + return req.get_response(self.application) + except Exception as ex: + LOG.exception(_("Caught error: %s"), unicode(ex)) + exc = webob.exc.HTTPInternalServerError() + return wsgi.Fault(exc) + + +class APIMapper(routes.Mapper): + def routematch(self, url=None, environ=None): + if url is "": + result = self._match("", environ) + return result[0], result[1] + return routes.Mapper.routematch(self, url, environ) + + +class ProjectMapper(APIMapper): + + def resource(self, member_name, collection_name, **kwargs): + if not ('parent_resource' in kwargs): + kwargs['path_prefix'] = '{project_id}/' + else: + parent_resource = kwargs['parent_resource'] + p_collection = parent_resource['collection_name'] + p_member = parent_resource['member_name'] + kwargs['path_prefix'] = '{project_id}/%s/:%s_id' % (p_collection, + p_member) + routes.Mapper.resource(self, member_name, + collection_name, + **kwargs) + + +class APIRouter(base_wsgi.Router): + """ + Routes requests on the OpenStack API to the appropriate controller + and method. + """ + + @classmethod + def factory(cls, global_config, **local_config): + """Simple paste factory, :class:`nova.wsgi.Router` doesn't have one""" + return cls() + + def __init__(self, ext_mgr=None): + self.server_members = {} + mapper = ProjectMapper() + self._setup_routes(mapper) + super(APIRouter, self).__init__(mapper) + + def _setup_routes(self, mapper): + server_members = self.server_members + server_members['action'] = 'POST' + if FLAGS.allow_admin_api: + LOG.debug(_("Including admin operations in API.")) + + server_members['diagnostics'] = 'GET' + server_members['actions'] = 'GET' + + mapper.resource("user", "users", + controller=users.create_resource(), + collection={'detail': 'GET'}) + + mapper.resource("account", "accounts", + controller=accounts.create_resource(), + collection={'detail': 'GET'}) + + mapper.resource("zone", "zones", + controller=zones.create_resource(), + collection={'detail': 'GET', + 'info': 'GET', + 'select': 'POST'}) + + mapper.connect("versions", "/", + controller=versions.create_resource(), + action='show') + + mapper.redirect("", "/") + + mapper.resource("console", "consoles", + controller=consoles.create_resource(), + parent_resource=dict(member_name='server', + collection_name='servers')) + + mapper.resource("server", "servers", + controller=servers.create_resource(), + collection={'detail': 'GET'}, + member=self.server_members) + + mapper.resource("ip", "ips", controller=ips.create_resource(), + parent_resource=dict(member_name='server', + collection_name='servers')) + + mapper.resource("image", "images", + controller=images.create_resource(), + collection={'detail': 'GET'}) + + mapper.resource("limit", "limits", + controller=limits.create_resource()) + + mapper.resource("flavor", "flavors", + controller=flavors.create_resource(), + collection={'detail': 'GET'}) + + image_metadata_controller = image_metadata.create_resource() + + mapper.resource("image_meta", "metadata", + controller=image_metadata_controller, + parent_resource=dict(member_name='image', + collection_name='images')) + + mapper.connect("metadata", "/{project_id}/images/{image_id}/metadata", + controller=image_metadata_controller, + action='update_all', + conditions={"method": ['PUT']}) + + server_metadata_controller = server_metadata.create_resource() + + mapper.resource("server_meta", "metadata", + controller=server_metadata_controller, + parent_resource=dict(member_name='server', + collection_name='servers')) + + mapper.connect("metadata", + "/{project_id}/servers/{server_id}/metadata", + controller=server_metadata_controller, + action='update_all', + conditions={"method": ['PUT']}) diff --git a/nova/api/openstack/accounts.py b/nova/api/openstack/v2/accounts.py index 3a19d5c89..0f1584261 100644 --- a/nova/api/openstack/accounts.py +++ b/nova/api/openstack/v2/accounts.py @@ -15,18 +15,16 @@ import webob.exc +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +from nova.auth import manager from nova import exception from nova import flags from nova import log as logging -from nova.auth import manager -from nova.api.openstack import faults -from nova.api.openstack import wsgi -from nova.api.openstack import xmlutil - FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack') +LOG = logging.getLogger('nova.api.openstack.v2.accounts') def _translate_keys(account): diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/v2/auth.py index d435f8318..c0ea30671 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/v2/auth.py @@ -19,25 +19,25 @@ import hashlib import os import time -import webob.exc import webob.dec +import webob.exc +from nova.api.openstack import common +from nova.api.openstack import wsgi from nova import auth from nova import context from nova import exception from nova import flags from nova import log as logging from nova import utils -from nova import wsgi -from nova.api.openstack import common -from nova.api.openstack import faults +from nova import wsgi as base_wsgi -LOG = logging.getLogger('nova.api.openstack') +LOG = logging.getLogger('nova.api.openstack.v2.auth') FLAGS = flags.FLAGS flags.DECLARE('use_forwarded_for', 'nova.api.auth') -class NoAuthMiddleware(wsgi.Middleware): +class NoAuthMiddleware(base_wsgi.Middleware): """Return a fake token if one isn't specified.""" @webob.dec.wsgify(RequestClass=wsgi.Request) @@ -73,7 +73,7 @@ class NoAuthMiddleware(wsgi.Middleware): return self.application -class AuthMiddleware(wsgi.Middleware): +class AuthMiddleware(base_wsgi.Middleware): """Authorize the openstack API request or return an HTTP Forbidden.""" def __init__(self, application, db_driver=None): @@ -92,12 +92,12 @@ class AuthMiddleware(wsgi.Middleware): token = req.headers["X-Auth-Token"] msg = _("%(user_id)s could not be found with token '%(token)s'") LOG.warn(msg % locals()) - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) # Get all valid projects for the user projects = self.auth.get_projects(user_id) if not projects: - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) project_id = "" path_parts = req.path.split('/') @@ -110,9 +110,9 @@ class AuthMiddleware(wsgi.Middleware): try: project = self.auth.get_project(project_id) except exception.ProjectNotFound: - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) if project_id not in [p.id for p in projects]: - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) else: # As a fallback, set project_id from the headers, which is the v1.0 # behavior. As a last resort, be forgiving to the user and set @@ -137,7 +137,7 @@ class AuthMiddleware(wsgi.Middleware): msg = _("%(user_id)s must be an admin or a " "member of %(project_id)s") LOG.warn(msg % locals()) - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) return self.application @@ -155,7 +155,7 @@ class AuthMiddleware(wsgi.Middleware): msg = _("Authentication requests must be made against a version " "root (e.g. /v1.0 or /v1.1).") LOG.warn(msg) - return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg)) + return wsgi.Fault(webob.exc.HTTPUnauthorized(explanation=msg)) def _get_auth_header(key): """Ensures that the KeyError returned is meaningful.""" @@ -169,7 +169,7 @@ class AuthMiddleware(wsgi.Middleware): except KeyError as ex: msg = _("Could not find %s in request.") % ex LOG.warn(msg) - return faults.Fault(webob.exc.HTTPUnauthorized(explanation=msg)) + return wsgi.Fault(webob.exc.HTTPUnauthorized(explanation=msg)) token, user = self._authorize_user(username, key, req) if user and token: @@ -184,7 +184,7 @@ class AuthMiddleware(wsgi.Middleware): LOG.debug(_("Successfully authenticated '%s'") % username) return res else: - return faults.Fault(webob.exc.HTTPUnauthorized()) + return wsgi.Fault(webob.exc.HTTPUnauthorized()) def authorize_token(self, token_hash): """ retrieves user information from the datastore given a token diff --git a/nova/api/openstack/consoles.py b/nova/api/openstack/v2/consoles.py index 7d8c0523e..ad0d8cbb4 100644 --- a/nova/api/openstack/consoles.py +++ b/nova/api/openstack/v2/consoles.py @@ -15,13 +15,13 @@ # License for the specific language governing permissions and limitations # under the License. -from webob import exc import webob +from webob import exc -from nova import console -from nova import exception from nova.api.openstack import wsgi from nova.api.openstack import xmlutil +from nova import console +from nova import exception def _translate_keys(cons): diff --git a/nova/api/openstack/contrib/__init__.py b/nova/api/openstack/v2/contrib/__init__.py index b3d4df69b..d361dac9c 100644 --- a/nova/api/openstack/contrib/__init__.py +++ b/nova/api/openstack/v2/contrib/__init__.py @@ -28,7 +28,7 @@ from nova import log as logging from nova import utils -LOG = logging.getLogger('nova.api.openstack.contrib') +LOG = logging.getLogger('nova.api.openstack.v2.contrib') def standard_extensions(ext_mgr): diff --git a/nova/api/openstack/contrib/admin_actions.py b/nova/api/openstack/v2/contrib/admin_actions.py index 81b23a8a0..632a8dc0e 100644 --- a/nova/api/openstack/contrib/admin_actions.py +++ b/nova/api/openstack/v2/contrib/admin_actions.py @@ -19,16 +19,16 @@ import traceback import webob from webob import exc +from nova.api.openstack.v2 import extensions from nova import compute from nova import exception from nova import flags from nova import log as logging -from nova.api.openstack import extensions from nova.scheduler import api as scheduler_api FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.contrib.admin_actions") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.admin_actions") class Admin_actions(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/contrib/createserverext.py b/nova/api/openstack/v2/contrib/createserverext.py index 4e6556f5d..a207d1bc5 100644 --- a/nova/api/openstack/contrib/createserverext.py +++ b/nova/api/openstack/v2/contrib/createserverext.py @@ -14,9 +14,9 @@ # License for the specific language governing permissions and limitations # under the License -from nova.api.openstack import extensions -from nova.api.openstack import servers -from nova.api.openstack import views +from nova.api.openstack.v2 import extensions +from nova.api.openstack.v2 import servers +from nova.api.openstack.v2 import views from nova.api.openstack import wsgi diff --git a/nova/api/openstack/contrib/deferred_delete.py b/nova/api/openstack/v2/contrib/deferred_delete.py index 8415ca4b3..95eb8f42c 100644 --- a/nova/api/openstack/contrib/deferred_delete.py +++ b/nova/api/openstack/v2/contrib/deferred_delete.py @@ -17,13 +17,13 @@ import webob +from nova.api.openstack.v2 import extensions +from nova.api.openstack.v2 import servers from nova import compute from nova import log as logging -from nova.api.openstack import extensions -from nova.api.openstack import servers -LOG = logging.getLogger("nova.api.contrib.deferred-delete") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.deferred-delete") class Deferred_delete(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/contrib/disk_config.py b/nova/api/openstack/v2/contrib/disk_config.py index 20da999a7..6e26c1daa 100644 --- a/nova/api/openstack/contrib/disk_config.py +++ b/nova/api/openstack/v2/contrib/disk_config.py @@ -16,11 +16,11 @@ """Disk Config extension.""" -from webob import exc from xml.dom import minidom -from nova.api.openstack import extensions -from nova.api.openstack import servers +from webob import exc + +from nova.api.openstack.v2 import extensions from nova.api.openstack import xmlutil from nova import compute from nova import log as logging diff --git a/nova/api/openstack/contrib/extended_status.py b/nova/api/openstack/v2/contrib/extended_status.py index 625f3ab2b..5e0a69780 100644 --- a/nova/api/openstack/contrib/extended_status.py +++ b/nova/api/openstack/v2/contrib/extended_status.py @@ -19,17 +19,16 @@ import traceback import webob from webob import exc +from nova.api.openstack.v2 import extensions +from nova.api.openstack import xmlutil from nova import compute from nova import exception from nova import flags from nova import log as logging -from nova.api.openstack import extensions -from nova.api.openstack import faults -from nova.api.openstack import xmlutil FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.contrib.extendedstatus") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.extendedstatus") class Extended_status(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/contrib/flavorextradata.py b/nova/api/openstack/v2/contrib/flavorextradata.py index f696d161b..0b0938054 100644 --- a/nova/api/openstack/contrib/flavorextradata.py +++ b/nova/api/openstack/v2/contrib/flavorextradata.py @@ -1,3 +1,5 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + # Copyright 2011 Canonical Ltd. # All Rights Reserved. # @@ -22,7 +24,7 @@ attributes. This extension adds to that list: swap """ -from nova.api.openstack import extensions +from nova.api.openstack.v2 import extensions class Flavorextradata(extensions.ExtensionDescriptor): @@ -32,5 +34,3 @@ class Flavorextradata(extensions.ExtensionDescriptor): alias = "os-flavor-extra-data" namespace = "http://docs.openstack.org/ext/flavor_extra_data/api/v1.1" updated = "2011-09-14T00:00:00+00:00" - -# vim: tabstop=4 shiftwidth=4 softtabstop=4 diff --git a/nova/api/openstack/contrib/flavorextraspecs.py b/nova/api/openstack/v2/contrib/flavorextraspecs.py index d71e9cf8b..bb38ea64e 100644 --- a/nova/api/openstack/contrib/flavorextraspecs.py +++ b/nova/api/openstack/v2/contrib/flavorextraspecs.py @@ -19,10 +19,9 @@ from webob import exc +from nova.api.openstack.v2 import extensions from nova import db from nova import exception -from nova.api.openstack import extensions -from nova.api.openstack import wsgi class FlavorExtraSpecsController(object): diff --git a/nova/api/openstack/contrib/floating_ips.py b/nova/api/openstack/v2/contrib/floating_ips.py index b64251e53..9689eac48 100644 --- a/nova/api/openstack/contrib/floating_ips.py +++ b/nova/api/openstack/v2/contrib/floating_ips.py @@ -15,17 +15,18 @@ # 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 webob +from nova.api.openstack.v2 import extensions from nova import compute from nova import exception from nova import log as logging from nova import network from nova import rpc -from nova.api.openstack import extensions -LOG = logging.getLogger('nova.api.openstack.contrib.floating_ips') +LOG = logging.getLogger('nova.api.openstack.v2.contrib.floating_ips') def _translate_floating_ip_view(floating_ip): diff --git a/nova/api/openstack/contrib/hosts.py b/nova/api/openstack/v2/contrib/hosts.py index 736843c3d..eb5074520 100644 --- a/nova/api/openstack/contrib/hosts.py +++ b/nova/api/openstack/v2/contrib/hosts.py @@ -17,17 +17,16 @@ import webob.exc +from nova.api.openstack import common +from nova.api.openstack.v2 import extensions from nova import compute from nova import exception from nova import flags from nova import log as logging -from nova.api.openstack import common -from nova.api.openstack import extensions -from nova.api.openstack import faults from nova.scheduler import api as scheduler_api -LOG = logging.getLogger("nova.api.hosts") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.hosts") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/contrib/keypairs.py b/nova/api/openstack/v2/contrib/keypairs.py index ee5cad530..e57d40001 100644 --- a/nova/api/openstack/contrib/keypairs.py +++ b/nova/api/openstack/v2/contrib/keypairs.py @@ -24,10 +24,10 @@ import tempfile import webob from webob import exc +from nova.api.openstack.v2 import extensions from nova import crypto from nova import db from nova import exception -from nova.api.openstack import extensions class KeypairController(object): diff --git a/nova/api/openstack/contrib/multinic.py b/nova/api/openstack/v2/contrib/multinic.py index 26968646d..561e246b5 100644 --- a/nova/api/openstack/contrib/multinic.py +++ b/nova/api/openstack/v2/contrib/multinic.py @@ -18,13 +18,13 @@ import webob from webob import exc -from nova.api.openstack import extensions +from nova.api.openstack.v2 import extensions from nova import compute from nova import exception from nova import log as logging -LOG = logging.getLogger("nova.api.multinic") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.multinic") # Note: The class name is as it has to be for this to be loaded as an diff --git a/nova/api/openstack/contrib/quotas.py b/nova/api/openstack/v2/contrib/quotas.py index 184b4d12f..7ad426c44 100644 --- a/nova/api/openstack/contrib/quotas.py +++ b/nova/api/openstack/v2/contrib/quotas.py @@ -17,10 +17,10 @@ import webob +from nova.api.openstack.v2 import extensions from nova import db from nova import exception from nova import quota -from nova.api.openstack import extensions class QuotaSetsController(object): diff --git a/nova/api/openstack/contrib/rescue.py b/nova/api/openstack/v2/contrib/rescue.py index d3f38b200..b63bf9ec5 100644 --- a/nova/api/openstack/contrib/rescue.py +++ b/nova/api/openstack/v2/contrib/rescue.py @@ -17,8 +17,7 @@ import webob from webob import exc -from nova.api.openstack import extensions as exts -from nova.api.openstack import faults +from nova.api.openstack.v2 import extensions as exts from nova import compute from nova import exception from nova import flags @@ -27,7 +26,7 @@ from nova import utils FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.contrib.rescue") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.rescue") class Rescue(exts.ExtensionDescriptor): diff --git a/nova/api/openstack/contrib/security_groups.py b/nova/api/openstack/v2/contrib/security_groups.py index fd1187629..50f129bd6 100644 --- a/nova/api/openstack/contrib/security_groups.py +++ b/nova/api/openstack/v2/contrib/security_groups.py @@ -16,25 +16,23 @@ """The security groups extension.""" import urllib +from xml.dom import minidom + from webob import exc import webob +from nova.api.openstack import common +from nova.api.openstack.v2 import extensions +from nova.api.openstack import wsgi from nova import compute from nova import db from nova import exception from nova import flags from nova import log as logging -from nova import rpc from nova import utils -from nova.api.openstack import common -from nova.api.openstack import extensions -from nova.api.openstack import wsgi -from nova.compute import power_state - -from xml.dom import minidom -LOG = logging.getLogger("nova.api.contrib.security_groups") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.security_groups") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/contrib/simple_tenant_usage.py b/nova/api/openstack/v2/contrib/simple_tenant_usage.py index 3399ac2be..e896371ed 100644 --- a/nova/api/openstack/contrib/simple_tenant_usage.py +++ b/nova/api/openstack/v2/contrib/simple_tenant_usage.py @@ -15,17 +15,18 @@ # License for the specific language governing permissions and limitations # under the License. +from datetime import datetime import urlparse + import webob +from webob import exc -from datetime import datetime -from nova import exception -from nova import flags +from nova.api.openstack.v2 import extensions +from nova.api.openstack.v2 import views from nova.compute import api -from nova.api.openstack import extensions -from nova.api.openstack import views from nova.db.sqlalchemy.session import get_session -from webob import exc +from nova import exception +from nova import flags FLAGS = flags.FLAGS diff --git a/nova/api/openstack/contrib/virtual_interfaces.py b/nova/api/openstack/v2/contrib/virtual_interfaces.py index 0afd2119d..1975a8dc0 100644 --- a/nova/api/openstack/contrib/virtual_interfaces.py +++ b/nova/api/openstack/v2/contrib/virtual_interfaces.py @@ -15,14 +15,14 @@ """The virtual interfaces extension.""" -from nova import log as logging -from nova import network from nova.api.openstack import common -from nova.api.openstack import extensions +from nova.api.openstack.v2 import extensions from nova.api.openstack import wsgi +from nova import log as logging +from nova import network -LOG = logging.getLogger("nova.api.virtual_interfaces") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.virtual_interfaces") def _translate_vif_summary_view(_context, vif): diff --git a/nova/api/openstack/contrib/virtual_storage_arrays.py b/nova/api/openstack/v2/contrib/virtual_storage_arrays.py index a6bf72960..f3a7831d5 100644 --- a/nova/api/openstack/contrib/virtual_storage_arrays.py +++ b/nova/api/openstack/v2/contrib/virtual_storage_arrays.py @@ -21,25 +21,25 @@ import webob from webob import exc -from nova import vsa -from nova import volume +from nova.api.openstack import common +from nova.api.openstack.v2.contrib import volumes +from nova.api.openstack.v2 import extensions +from nova.api.openstack.v2 import servers +from nova.api.openstack import wsgi from nova import compute +from nova.compute import instance_types from nova import network from nova import db from nova import quota from nova import exception +from nova import flags from nova import log as logging -from nova.api.openstack import common -from nova.api.openstack import extensions -from nova.api.openstack import wsgi -from nova.api.openstack import servers -from nova.api.openstack.contrib import volumes -from nova.compute import instance_types +from nova import vsa +from nova import volume -from nova import flags FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.vsa") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.vsa") def _vsa_view(context, vsa, details=False, instances=None): diff --git a/nova/api/openstack/contrib/volumes.py b/nova/api/openstack/v2/contrib/volumes.py index 917cfc61b..5d86282f2 100644 --- a/nova/api/openstack/contrib/volumes.py +++ b/nova/api/openstack/v2/contrib/volumes.py @@ -18,6 +18,9 @@ from webob import exc import webob +from nova.api.openstack import common +from nova.api.openstack.v2 import extensions +from nova.api.openstack.v2 import servers from nova import compute from nova import db from nova import exception @@ -26,12 +29,9 @@ from nova import log as logging from nova import quota from nova import volume from nova.volume import volume_types -from nova.api.openstack import common -from nova.api.openstack import extensions -from nova.api.openstack import servers -LOG = logging.getLogger("nova.api.volumes") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.volumes") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/contrib/volumetypes.py b/nova/api/openstack/v2/contrib/volumetypes.py index 64a9e0f02..ca3866c99 100644 --- a/nova/api/openstack/contrib/volumetypes.py +++ b/nova/api/openstack/v2/contrib/volumetypes.py @@ -19,11 +19,11 @@ from webob import exc +from nova.api.openstack.v2 import extensions +from nova.api.openstack import wsgi from nova import db from nova import exception from nova.volume import volume_types -from nova.api.openstack import extensions -from nova.api.openstack import wsgi class VolumeTypesController(object): diff --git a/nova/api/openstack/contrib/zones.py b/nova/api/openstack/v2/contrib/zones.py index 628b8182f..76a235713 100644 --- a/nova/api/openstack/contrib/zones.py +++ b/nova/api/openstack/v2/contrib/zones.py @@ -20,10 +20,10 @@ from nova import flags from nova import log as logging -from nova.api.openstack import extensions +from nova.api.openstack.v2 import extensions -LOG = logging.getLogger("nova.api.zones") +LOG = logging.getLogger("nova.api.openstack.v2.contrib.zones") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/v2/extensions.py index 7da10513e..a5cf863ed 100644 --- a/nova/api/openstack/extensions.py +++ b/nova/api/openstack/v2/extensions.py @@ -27,18 +27,18 @@ import routes import webob.dec import webob.exc +import nova.api.openstack.v2 +from nova.api.openstack import common +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil from nova import exception from nova import flags from nova import log as logging from nova import utils from nova import wsgi as base_wsgi -import nova.api.openstack -from nova.api.openstack import common -from nova.api.openstack import wsgi -from nova.api.openstack import xmlutil -LOG = logging.getLogger('nova.api.openstack.extensions') +LOG = logging.getLogger('nova.api.openstack.v2.extensions') FLAGS = flags.FLAGS @@ -273,7 +273,7 @@ class ExtensionMiddleware(base_wsgi.Middleware): ext_mgr = ExtensionManager() self.ext_mgr = ext_mgr - mapper = nova.api.openstack.ProjectMapper() + mapper = nova.api.openstack.v2.ProjectMapper() serializer = wsgi.ResponseSerializer( {'application/xml': ExtensionsXMLSerializer()}) diff --git a/nova/api/openstack/flavors.py b/nova/api/openstack/v2/flavors.py index 7680ef1ca..d5b673c7f 100644 --- a/nova/api/openstack/flavors.py +++ b/nova/api/openstack/v2/flavors.py @@ -15,10 +15,10 @@ # License for the specific language governing permissions and limitations # under the License. -import webob from lxml import etree +import webob -from nova.api.openstack.views import flavors as flavors_view +from nova.api.openstack.v2.views import flavors as flavors_view from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.compute import instance_types diff --git a/nova/api/openstack/image_metadata.py b/nova/api/openstack/v2/image_metadata.py index adb6bee4b..e3cfac4e0 100644 --- a/nova/api/openstack/image_metadata.py +++ b/nova/api/openstack/v2/image_metadata.py @@ -17,12 +17,12 @@ from webob import exc +from nova.api.openstack import common +from nova.api.openstack import wsgi from nova import exception from nova import flags from nova import image from nova import utils -from nova.api.openstack import common -from nova.api.openstack import wsgi FLAGS = flags.FLAGS diff --git a/nova/api/openstack/images.py b/nova/api/openstack/v2/images.py index f3ef63b49..84b7b17db 100644 --- a/nova/api/openstack/images.py +++ b/nova/api/openstack/v2/images.py @@ -18,20 +18,18 @@ import os.path from lxml import etree import webob.exc +from nova.api.openstack import common +from nova.api.openstack.v2.views import images as views_images +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil from nova import compute from nova import exception from nova import flags import nova.image from nova import log -from nova.api.openstack import common -from nova.api.openstack import image_metadata -from nova.api.openstack import servers -from nova.api.openstack import wsgi -from nova.api.openstack import xmlutil -from nova.api.openstack.views import images as views_images -LOG = log.getLogger('nova.api.openstack.images') +LOG = log.getLogger('nova.api.openstack.v2.images') FLAGS = flags.FLAGS SUPPORTED_FILTERS = { diff --git a/nova/api/openstack/ips.py b/nova/api/openstack/v2/ips.py index 2bef453a2..705754665 100644 --- a/nova/api/openstack/ips.py +++ b/nova/api/openstack/v2/ips.py @@ -16,19 +16,18 @@ # under the License. from lxml import etree - from webob import exc import nova from nova.api.openstack import common +from nova.api.openstack.v2.views import addresses as view_addresses from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.views import addresses as view_addresses from nova import log as logging from nova import flags -LOG = logging.getLogger('nova.api.openstack.ips') +LOG = logging.getLogger('nova.api.openstack.v2.ips') FLAGS = flags.FLAGS diff --git a/nova/api/openstack/limits.py b/nova/api/openstack/v2/limits.py index 56e839526..04ff9e647 100644 --- a/nova/api/openstack/limits.py +++ b/nova/api/openstack/v2/limits.py @@ -17,28 +17,26 @@ Module dedicated functions/classes dealing with rate limiting requests. """ +from collections import defaultdict import copy import httplib import json -from lxml import etree import math import re import time import urllib -import webob.exc - -from collections import defaultdict +from lxml import etree from webob.dec import wsgify +import webob.exc -from nova import quota -from nova import utils -from nova import wsgi as base_wsgi from nova.api.openstack import common -from nova.api.openstack import faults -from nova.api.openstack.views import limits as limits_views +from nova.api.openstack.v2.views import limits as limits_views from nova.api.openstack import wsgi from nova.api.openstack import xmlutil +from nova import quota +from nova import utils +from nova import wsgi as base_wsgi # Convenience constants for the limits dictionary passed to Limiter(). @@ -275,7 +273,7 @@ class RateLimitingMiddleware(base_wsgi.Middleware): if delay: msg = _("This request was rate-limited.") retry = time.time() + delay - return faults.OverLimitFault(msg, error, retry) + return wsgi.OverLimitFault(msg, error, retry) req.environ["nova.limits"] = self._limiter.get_limits(username) diff --git a/nova/api/openstack/ratelimiting/__init__.py b/nova/api/openstack/v2/ratelimiting/__init__.py index 9ede548c2..78dc465a7 100644 --- a/nova/api/openstack/ratelimiting/__init__.py +++ b/nova/api/openstack/v2/ratelimiting/__init__.py @@ -20,11 +20,12 @@ import httplib import time import urllib + import webob.dec import webob.exc from nova import wsgi -from nova.api.openstack import faults +from nova.api.openstack import wsgi as os_wsgi # Convenience constants for the limits dictionary passed to Limiter(). PER_SECOND = 1 @@ -83,7 +84,7 @@ class RateLimitingMiddleware(wsgi.Middleware): exc = webob.exc.HTTPRequestEntityTooLarge( explanation=('Too many requests.'), headers={'Retry-After': time.time() + delay}) - raise faults.Fault(exc) + raise os_wsgi.Fault(exc) return application def get_delay(self, action_name, username): diff --git a/nova/api/openstack/schemas/atom-link.rng b/nova/api/openstack/v2/schemas/atom-link.rng index edba5eee6..edba5eee6 100644 --- a/nova/api/openstack/schemas/atom-link.rng +++ b/nova/api/openstack/v2/schemas/atom-link.rng diff --git a/nova/api/openstack/schemas/atom.rng b/nova/api/openstack/v2/schemas/atom.rng index c2df4e410..c2df4e410 100644 --- a/nova/api/openstack/schemas/atom.rng +++ b/nova/api/openstack/v2/schemas/atom.rng diff --git a/nova/api/openstack/schemas/v1.1/addresses.rng b/nova/api/openstack/v2/schemas/v1.1/addresses.rng index b498e8a63..b498e8a63 100644 --- a/nova/api/openstack/schemas/v1.1/addresses.rng +++ b/nova/api/openstack/v2/schemas/v1.1/addresses.rng diff --git a/nova/api/openstack/schemas/v1.1/extension.rng b/nova/api/openstack/v2/schemas/v1.1/extension.rng index 336659755..336659755 100644 --- a/nova/api/openstack/schemas/v1.1/extension.rng +++ b/nova/api/openstack/v2/schemas/v1.1/extension.rng diff --git a/nova/api/openstack/schemas/v1.1/extensions.rng b/nova/api/openstack/v2/schemas/v1.1/extensions.rng index 4d8bff646..4d8bff646 100644 --- a/nova/api/openstack/schemas/v1.1/extensions.rng +++ b/nova/api/openstack/v2/schemas/v1.1/extensions.rng diff --git a/nova/api/openstack/schemas/v1.1/flavor.rng b/nova/api/openstack/v2/schemas/v1.1/flavor.rng index 6d3adc8dc..6d3adc8dc 100644 --- a/nova/api/openstack/schemas/v1.1/flavor.rng +++ b/nova/api/openstack/v2/schemas/v1.1/flavor.rng diff --git a/nova/api/openstack/schemas/v1.1/flavors.rng b/nova/api/openstack/v2/schemas/v1.1/flavors.rng index b7a3acc01..b7a3acc01 100644 --- a/nova/api/openstack/schemas/v1.1/flavors.rng +++ b/nova/api/openstack/v2/schemas/v1.1/flavors.rng diff --git a/nova/api/openstack/schemas/v1.1/flavors_index.rng b/nova/api/openstack/v2/schemas/v1.1/flavors_index.rng index d1a4fedb1..d1a4fedb1 100644 --- a/nova/api/openstack/schemas/v1.1/flavors_index.rng +++ b/nova/api/openstack/v2/schemas/v1.1/flavors_index.rng diff --git a/nova/api/openstack/schemas/v1.1/image.rng b/nova/api/openstack/v2/schemas/v1.1/image.rng index 505081fba..505081fba 100644 --- a/nova/api/openstack/schemas/v1.1/image.rng +++ b/nova/api/openstack/v2/schemas/v1.1/image.rng diff --git a/nova/api/openstack/schemas/v1.1/images.rng b/nova/api/openstack/v2/schemas/v1.1/images.rng index 064d4d9cc..064d4d9cc 100644 --- a/nova/api/openstack/schemas/v1.1/images.rng +++ b/nova/api/openstack/v2/schemas/v1.1/images.rng diff --git a/nova/api/openstack/schemas/v1.1/images_index.rng b/nova/api/openstack/v2/schemas/v1.1/images_index.rng index 3db0b2672..3db0b2672 100644 --- a/nova/api/openstack/schemas/v1.1/images_index.rng +++ b/nova/api/openstack/v2/schemas/v1.1/images_index.rng diff --git a/nova/api/openstack/schemas/v1.1/limits.rng b/nova/api/openstack/v2/schemas/v1.1/limits.rng index 1af8108ec..1af8108ec 100644 --- a/nova/api/openstack/schemas/v1.1/limits.rng +++ b/nova/api/openstack/v2/schemas/v1.1/limits.rng diff --git a/nova/api/openstack/schemas/v1.1/metadata.rng b/nova/api/openstack/v2/schemas/v1.1/metadata.rng index b2f5d702a..b2f5d702a 100644 --- a/nova/api/openstack/schemas/v1.1/metadata.rng +++ b/nova/api/openstack/v2/schemas/v1.1/metadata.rng diff --git a/nova/api/openstack/schemas/v1.1/server.rng b/nova/api/openstack/v2/schemas/v1.1/server.rng index 2e86ccffe..2e86ccffe 100644 --- a/nova/api/openstack/schemas/v1.1/server.rng +++ b/nova/api/openstack/v2/schemas/v1.1/server.rng diff --git a/nova/api/openstack/schemas/v1.1/servers.rng b/nova/api/openstack/v2/schemas/v1.1/servers.rng index 4e2bb8853..4e2bb8853 100644 --- a/nova/api/openstack/schemas/v1.1/servers.rng +++ b/nova/api/openstack/v2/schemas/v1.1/servers.rng diff --git a/nova/api/openstack/schemas/v1.1/servers_index.rng b/nova/api/openstack/v2/schemas/v1.1/servers_index.rng index 023e4b66a..023e4b66a 100644 --- a/nova/api/openstack/schemas/v1.1/servers_index.rng +++ b/nova/api/openstack/v2/schemas/v1.1/servers_index.rng diff --git a/nova/api/openstack/schemas/v1.1/version.rng b/nova/api/openstack/v2/schemas/v1.1/version.rng index ae76270ba..ae76270ba 100644 --- a/nova/api/openstack/schemas/v1.1/version.rng +++ b/nova/api/openstack/v2/schemas/v1.1/version.rng diff --git a/nova/api/openstack/schemas/v1.1/versions.rng b/nova/api/openstack/v2/schemas/v1.1/versions.rng index 8b2cc7f71..8b2cc7f71 100644 --- a/nova/api/openstack/schemas/v1.1/versions.rng +++ b/nova/api/openstack/v2/schemas/v1.1/versions.rng diff --git a/nova/api/openstack/server_metadata.py b/nova/api/openstack/v2/server_metadata.py index 4145898c1..47dbe2fbd 100644 --- a/nova/api/openstack/server_metadata.py +++ b/nova/api/openstack/v2/server_metadata.py @@ -17,9 +17,9 @@ from webob import exc -from nova import compute from nova.api.openstack import common from nova.api.openstack import wsgi +from nova import compute from nova import exception diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/v2/servers.py index 8b11b30f6..1ae7f80bf 100644 --- a/nova/api/openstack/servers.py +++ b/nova/api/openstack/v2/servers.py @@ -23,13 +23,12 @@ from webob import exc import webob from xml.dom import minidom -import nova.api.openstack from nova.api.openstack import common -from nova.api.openstack import ips -from nova.api.openstack.views import addresses as views_addresses -from nova.api.openstack.views import flavors as views_flavors -from nova.api.openstack.views import images as views_images -from nova.api.openstack.views import servers as views_servers +from nova.api.openstack.v2 import ips +from nova.api.openstack.v2.views import addresses as views_addresses +from nova.api.openstack.v2.views import flavors as views_flavors +from nova.api.openstack.v2.views import images as views_images +from nova.api.openstack.v2.views import servers as views_servers from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -45,7 +44,7 @@ from nova.scheduler import api as scheduler_api from nova import utils -LOG = logging.getLogger('nova.api.openstack.servers') +LOG = logging.getLogger('nova.api.openstack.v2.servers') FLAGS = flags.FLAGS diff --git a/nova/api/openstack/urlmap.py b/nova/api/openstack/v2/urlmap.py index 199fa6130..bae69198e 100644 --- a/nova/api/openstack/urlmap.py +++ b/nova/api/openstack/v2/urlmap.py @@ -28,7 +28,7 @@ _option_header_piece_re = re.compile(r';\s*([^\s;=]+|%s)\s*' r'(?:=\s*([^;]+|%s))?\s*' % (_quoted_string_re, _quoted_string_re)) -LOG = logging.getLogger('nova.api.openstack.map') +LOG = logging.getLogger('nova.api.openstack.v2.map') def unquote_header_value(value): diff --git a/nova/api/openstack/users.py b/nova/api/openstack/v2/users.py index 9fac45763..9dba79e03 100644 --- a/nova/api/openstack/users.py +++ b/nova/api/openstack/v2/users.py @@ -15,17 +15,17 @@ from webob import exc -from nova import exception -from nova import flags -from nova import log as logging from nova.api.openstack import common from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.auth import manager +from nova import exception +from nova import flags +from nova import log as logging FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack') +LOG = logging.getLogger('nova.api.openstack.users') def _translate_keys(user): diff --git a/nova/api/openstack/versions.py b/nova/api/openstack/v2/versions.py index 5461ffce2..3c3d4068c 100644 --- a/nova/api/openstack/versions.py +++ b/nova/api/openstack/v2/versions.py @@ -16,11 +16,12 @@ # under the License. from datetime import datetime + from lxml import etree import webob import webob.dec -import nova.api.openstack.views.versions +from nova.api.openstack.v2.views import versions as views_versions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil @@ -84,7 +85,7 @@ class Versions(wsgi.Resource): def dispatch(self, request, *args): """Respond to a request for all OpenStack API versions.""" - builder = nova.api.openstack.views.versions.get_view_builder(request) + builder = views_versions.get_view_builder(request) if request.path == '/': # List Versions return builder.build_versions(VERSIONS) @@ -95,7 +96,7 @@ class Versions(wsgi.Resource): class VersionV11(object): def show(self, req): - builder = nova.api.openstack.views.versions.get_view_builder(req) + builder = views_versions.get_view_builder(req) return builder.build_version(VERSIONS['v1.1']) diff --git a/nova/api/openstack/views/__init__.py b/nova/api/openstack/v2/views/__init__.py index e69de29bb..e69de29bb 100644 --- a/nova/api/openstack/views/__init__.py +++ b/nova/api/openstack/v2/views/__init__.py diff --git a/nova/api/openstack/views/addresses.py b/nova/api/openstack/v2/views/addresses.py index 1dbcaffe0..6f518b11a 100644 --- a/nova/api/openstack/views/addresses.py +++ b/nova/api/openstack/v2/views/addresses.py @@ -23,7 +23,7 @@ from nova import log as logging FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack.views.addresses') +LOG = logging.getLogger('nova.api.openstack.v2.views.addresses') class ViewBuilder(common.ViewBuilder): diff --git a/nova/api/openstack/views/flavors.py b/nova/api/openstack/v2/views/flavors.py index f84ae5987..7b170a6b2 100644 --- a/nova/api/openstack/views/flavors.py +++ b/nova/api/openstack/v2/views/flavors.py @@ -17,7 +17,6 @@ import os.path - from nova.api.openstack import common diff --git a/nova/api/openstack/views/images.py b/nova/api/openstack/v2/views/images.py index c4cfe8031..c4cfe8031 100644 --- a/nova/api/openstack/views/images.py +++ b/nova/api/openstack/v2/views/images.py diff --git a/nova/api/openstack/views/limits.py b/nova/api/openstack/v2/views/limits.py index 138a40cb8..138a40cb8 100644 --- a/nova/api/openstack/views/limits.py +++ b/nova/api/openstack/v2/views/limits.py diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/v2/views/servers.py index e6f4bc2c4..979be930f 100644 --- a/nova/api/openstack/views/servers.py +++ b/nova/api/openstack/v2/views/servers.py @@ -17,19 +17,16 @@ # under the License. import hashlib -import os from nova.api.openstack import common -from nova.api.openstack.views import addresses as views_addresses -from nova.api.openstack.views import flavors as views_flavors -from nova.api.openstack.views import images as views_images -from nova.compute import vm_states -from nova import exception +from nova.api.openstack.v2.views import addresses as views_addresses +from nova.api.openstack.v2.views import flavors as views_flavors +from nova.api.openstack.v2.views import images as views_images from nova import log as logging from nova import utils -LOG = logging.getLogger('nova.api.openstack.views.servers') +LOG = logging.getLogger('nova.api.openstack.v2.views.servers') class ViewBuilder(common.ViewBuilder): diff --git a/nova/api/openstack/views/versions.py b/nova/api/openstack/v2/views/versions.py index 1ac398706..1ac398706 100644 --- a/nova/api/openstack/views/versions.py +++ b/nova/api/openstack/v2/views/versions.py diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/v2/zones.py index 2a95cd0a4..8c5add2d1 100644 --- a/nova/api/openstack/zones.py +++ b/nova/api/openstack/v2/zones.py @@ -16,25 +16,23 @@ import json import urlparse +from nova.api.openstack import common +from nova.api.openstack.v2 import servers +from nova.api.openstack import xmlutil +from nova.api.openstack import wsgi +from nova.compute import api as compute from nova import crypto from nova import db from nova import exception from nova import flags from nova import log as logging - -from nova.compute import api as compute from nova.scheduler import api -from nova.api.openstack import common -from nova.api.openstack import servers -from nova.api.openstack import xmlutil -from nova.api.openstack import wsgi - FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack.zones') +LOG = logging.getLogger('nova.api.openstack.v2.zones') def _filter_keys(item, keys): diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 8c6b30ca9..7e4875066 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -15,13 +15,11 @@ # License for the specific language governing permissions and limitations # under the License. -import json from lxml import etree import webob from xml.dom import minidom from xml.parsers import expat -import faults from nova import exception from nova import log as logging from nova import utils @@ -528,7 +526,7 @@ class Resource(wsgi.Application): serialized by requested content type. Exceptions derived from webob.exc.HTTPException will be automatically - wrapped in faults.Fault() to provide API friendly error responses. + wrapped in Fault() to provide API friendly error responses. """ @@ -556,10 +554,10 @@ class Resource(wsgi.Application): action, args, accept = self.deserializer.deserialize(request) except exception.InvalidContentType: msg = _("Unsupported Content-Type") - return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg)) + return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") - return faults.Fault(webob.exc.HTTPBadRequest(explanation=msg)) + return Fault(webob.exc.HTTPBadRequest(explanation=msg)) project_id = args.pop("project_id", None) if 'nova.context' in request.environ and project_id: @@ -567,12 +565,12 @@ class Resource(wsgi.Application): try: action_result = self.dispatch(request, action, args) - except faults.Fault as ex: + except Fault as ex: LOG.info(_("Fault thrown: %s"), unicode(ex)) action_result = ex except webob.exc.HTTPException as ex: LOG.info(_("HTTP exception thrown: %s"), unicode(ex)) - action_result = faults.Fault(ex) + action_result = Fault(ex) if type(action_result) is dict or action_result is None: response = self.serializer.serialize(request, @@ -601,7 +599,7 @@ class Resource(wsgi.Application): return controller_method(req=request, **action_args) except TypeError as exc: LOG.exception(exc) - return faults.Fault(webob.exc.HTTPBadRequest()) + return Fault(webob.exc.HTTPBadRequest()) class Controller(object): @@ -612,3 +610,96 @@ class Controller(object): def __init__(self, view_builder=None): """Initialize controller with a view builder instance.""" self._view_builder = view_builder or self._view_builder_class() + + +class Fault(webob.exc.HTTPException): + """Wrap webob.exc.HTTPException to provide API friendly response.""" + + _fault_names = { + 400: "badRequest", + 401: "unauthorized", + 403: "resizeNotAllowed", + 404: "itemNotFound", + 405: "badMethod", + 409: "inProgress", + 413: "overLimit", + 415: "badMediaType", + 501: "notImplemented", + 503: "serviceUnavailable"} + + def __init__(self, exception): + """Create a Fault for the given webob.exc.exception.""" + self.wrapped_exc = exception + self.status_int = exception.status_int + + @webob.dec.wsgify(RequestClass=Request) + def __call__(self, req): + """Generate a WSGI response based on the exception passed to ctor.""" + # Replace the body with fault details. + code = self.wrapped_exc.status_int + fault_name = self._fault_names.get(code, "cloudServersFault") + fault_data = { + fault_name: { + 'code': code, + 'message': self.wrapped_exc.explanation}} + if code == 413: + retry = self.wrapped_exc.headers['Retry-After'] + fault_data[fault_name]['retryAfter'] = retry + + # 'code' is an attribute on the fault tag itself + metadata = {'attributes': {fault_name: 'code'}} + + xml_serializer = XMLDictSerializer(metadata, XMLNS_V11) + + content_type = req.best_match_content_type() + serializer = { + 'application/xml': xml_serializer, + 'application/json': JSONDictSerializer(), + }[content_type] + + self.wrapped_exc.body = serializer.serialize(fault_data) + self.wrapped_exc.content_type = content_type + + return self.wrapped_exc + + def __str__(self): + return self.wrapped_exc.__str__() + + +class OverLimitFault(webob.exc.HTTPException): + """ + Rate-limited request response. + """ + + def __init__(self, message, details, retry_time): + """ + Initialize new `OverLimitFault` with relevant information. + """ + self.wrapped_exc = webob.exc.HTTPRequestEntityTooLarge() + self.content = { + "overLimitFault": { + "code": self.wrapped_exc.status_int, + "message": message, + "details": details, + }, + } + + @webob.dec.wsgify(RequestClass=Request) + def __call__(self, request): + """ + Return the wrapped exception with a serialized body conforming to our + error format. + """ + content_type = request.best_match_content_type() + metadata = {"attributes": {"overLimitFault": "code"}} + + xml_serializer = XMLDictSerializer(metadata, XMLNS_V11) + serializer = { + 'application/xml': xml_serializer, + 'application/json': JSONDictSerializer(), + }[content_type] + + content = serializer.serialize(self.content) + self.wrapped_exc.body = content + + return self.wrapped_exc diff --git a/nova/api/openstack/xmlutil.py b/nova/api/openstack/xmlutil.py index 5779849b3..db490e652 100644 --- a/nova/api/openstack/xmlutil.py +++ b/nova/api/openstack/xmlutil.py @@ -31,9 +31,9 @@ XMLNS_ATOM = 'http://www.w3.org/2005/Atom' def validate_schema(xml, schema_name): if type(xml) is str: xml = etree.fromstring(xml) - base_path = 'nova/api/openstack/schemas/v1.1/' + base_path = 'nova/api/openstack/v2/schemas/v1.1/' if schema_name in ('atom', 'atom-link'): - base_path = 'nova/api/openstack/schemas/' + base_path = 'nova/api/openstack/v2/schemas/' schema_path = os.path.join(utils.novadir(), '%s%s.rng' % (base_path, schema_name)) schema_doc = etree.parse(schema_path) |
