diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-01-13 19:19:46 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-01-13 19:19:46 +0000 |
| commit | 6c898e6abf44caa176790e9cd4505aeed145397c (patch) | |
| tree | 4d9cbc1ef13d8d208284417f333e36482bdd8c26 /nova/api | |
| parent | 485328e48fc7dff1ce2ebfd262c442d8f993688b (diff) | |
| parent | 60ff2e3b72b5a3c9200f8fc47aac01cdb610bdcf (diff) | |
| download | nova-6c898e6abf44caa176790e9cd4505aeed145397c.tar.gz nova-6c898e6abf44caa176790e9cd4505aeed145397c.tar.xz nova-6c898e6abf44caa176790e9cd4505aeed145397c.zip | |
Merge "Implements blueprint separate-nova-volumeapi"
Diffstat (limited to 'nova/api')
| -rw-r--r-- | nova/api/mapper.py | 76 | ||||
| -rw-r--r-- | nova/api/openstack/__init__.py | 69 | ||||
| -rw-r--r-- | nova/api/openstack/auth.py (renamed from nova/api/openstack/v2/auth.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/__init__.py (renamed from nova/api/openstack/v2/__init__.py) | 62 | ||||
| -rw-r--r-- | nova/api/openstack/compute/consoles.py (renamed from nova/api/openstack/v2/consoles.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/__init__.py | 32 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/accounts.py (renamed from nova/api/openstack/v2/contrib/accounts.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/admin_actions.py (renamed from nova/api/openstack/v2/contrib/admin_actions.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/cloudpipe.py (renamed from nova/api/openstack/v2/contrib/cloudpipe.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/console_output.py (renamed from nova/api/openstack/v2/contrib/console_output.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/createserverext.py (renamed from nova/api/openstack/v2/contrib/createserverext.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/deferred_delete.py (renamed from nova/api/openstack/v2/contrib/deferred_delete.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/disk_config.py (renamed from nova/api/openstack/v2/contrib/disk_config.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/extended_status.py (renamed from nova/api/openstack/v2/contrib/extended_status.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/flavorextradata.py (renamed from nova/api/openstack/v2/contrib/flavorextradata.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/flavorextraspecs.py (renamed from nova/api/openstack/v2/contrib/flavorextraspecs.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/floating_ip_dns.py (renamed from nova/api/openstack/v2/contrib/floating_ip_dns.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/floating_ip_pools.py (renamed from nova/api/openstack/v2/contrib/floating_ip_pools.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/floating_ips.py (renamed from nova/api/openstack/v2/contrib/floating_ips.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/hosts.py (renamed from nova/api/openstack/v2/contrib/hosts.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/keypairs.py (renamed from nova/api/openstack/v2/contrib/keypairs.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/multinic.py (renamed from nova/api/openstack/v2/contrib/multinic.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/networks.py (renamed from nova/api/openstack/v2/contrib/networks.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/quotas.py (renamed from nova/api/openstack/v2/contrib/quotas.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/rescue.py (renamed from nova/api/openstack/v2/contrib/rescue.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/security_groups.py (renamed from nova/api/openstack/v2/contrib/security_groups.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/server_action_list.py (renamed from nova/api/openstack/v2/contrib/server_action_list.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/server_diagnostics.py (renamed from nova/api/openstack/v2/contrib/server_diagnostics.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/simple_tenant_usage.py (renamed from nova/api/openstack/v2/contrib/simple_tenant_usage.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/users.py (renamed from nova/api/openstack/v2/contrib/users.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/virtual_interfaces.py (renamed from nova/api/openstack/v2/contrib/virtual_interfaces.py) | 5 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/virtual_storage_arrays.py (renamed from nova/api/openstack/v2/contrib/virtual_storage_arrays.py) | 8 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/volumes.py (renamed from nova/api/openstack/v2/contrib/volumes.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/volumetypes.py (renamed from nova/api/openstack/v2/contrib/volumetypes.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/contrib/zones.py (renamed from nova/api/openstack/v2/contrib/zones.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/extensions.py | 45 | ||||
| -rw-r--r-- | nova/api/openstack/compute/flavors.py (renamed from nova/api/openstack/v2/flavors.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/image_metadata.py (renamed from nova/api/openstack/v2/image_metadata.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/images.py (renamed from nova/api/openstack/v2/images.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/ips.py (renamed from nova/api/openstack/v2/ips.py) | 4 | ||||
| -rw-r--r-- | nova/api/openstack/compute/limits.py (renamed from nova/api/openstack/v2/limits.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/ratelimiting/__init__.py (renamed from nova/api/openstack/v2/ratelimiting/__init__.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/atom-link.rng (renamed from nova/api/openstack/v2/schemas/atom-link.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/atom.rng (renamed from nova/api/openstack/v2/schemas/atom.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/addresses.rng (renamed from nova/api/openstack/v2/schemas/v1.1/addresses.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/extension.rng (renamed from nova/api/openstack/v2/schemas/v1.1/extension.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/extensions.rng (renamed from nova/api/openstack/v2/schemas/v1.1/extensions.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/flavor.rng (renamed from nova/api/openstack/v2/schemas/v1.1/flavor.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/flavors.rng (renamed from nova/api/openstack/v2/schemas/v1.1/flavors.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/flavors_index.rng (renamed from nova/api/openstack/v2/schemas/v1.1/flavors_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/image.rng (renamed from nova/api/openstack/v2/schemas/v1.1/image.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/images.rng (renamed from nova/api/openstack/v2/schemas/v1.1/images.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/images_index.rng (renamed from nova/api/openstack/v2/schemas/v1.1/images_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/limits.rng (renamed from nova/api/openstack/v2/schemas/v1.1/limits.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/metadata.rng (renamed from nova/api/openstack/v2/schemas/v1.1/metadata.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/server.rng (renamed from nova/api/openstack/v2/schemas/v1.1/server.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/servers.rng (renamed from nova/api/openstack/v2/schemas/v1.1/servers.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/servers_index.rng (renamed from nova/api/openstack/v2/schemas/v1.1/servers_index.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/version.rng (renamed from nova/api/openstack/v2/schemas/v1.1/version.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/schemas/v1.1/versions.rng (renamed from nova/api/openstack/v2/schemas/v1.1/versions.rng) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/server_metadata.py (renamed from nova/api/openstack/v2/server_metadata.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/servers.py (renamed from nova/api/openstack/v2/servers.py) | 6 | ||||
| -rw-r--r-- | nova/api/openstack/compute/versions.py (renamed from nova/api/openstack/v2/versions.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/__init__.py (renamed from nova/api/openstack/v2/views/__init__.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/addresses.py (renamed from nova/api/openstack/v2/views/addresses.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/flavors.py (renamed from nova/api/openstack/v2/views/flavors.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/images.py (renamed from nova/api/openstack/v2/views/images.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/limits.py (renamed from nova/api/openstack/v2/views/limits.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/servers.py (renamed from nova/api/openstack/v2/views/servers.py) | 8 | ||||
| -rw-r--r-- | nova/api/openstack/compute/views/versions.py (renamed from nova/api/openstack/v2/views/versions.py) | 0 | ||||
| -rw-r--r-- | nova/api/openstack/extensions.py (renamed from nova/api/openstack/v2/extensions.py) | 80 | ||||
| -rw-r--r-- | nova/api/openstack/urlmap.py (renamed from nova/api/openstack/v2/urlmap.py) | 2 | ||||
| -rw-r--r-- | nova/api/openstack/v2/contrib/__init__.py | 90 | ||||
| -rw-r--r-- | nova/api/openstack/volume/__init__.py | 99 | ||||
| -rw-r--r-- | nova/api/openstack/volume/contrib/__init__.py | 32 | ||||
| -rw-r--r-- | nova/api/openstack/volume/extensions.py | 44 | ||||
| -rw-r--r-- | nova/api/openstack/volume/snapshots.py | 183 | ||||
| -rw-r--r-- | nova/api/openstack/volume/types.py | 89 | ||||
| -rw-r--r-- | nova/api/openstack/volume/versions.py | 83 | ||||
| -rw-r--r-- | nova/api/openstack/volume/views/__init__.py | 16 | ||||
| -rw-r--r-- | nova/api/openstack/volume/views/versions.py | 37 | ||||
| -rw-r--r-- | nova/api/openstack/volume/volumes.py | 254 | ||||
| -rw-r--r-- | nova/api/openstack/xmlutil.py | 4 |
83 files changed, 1210 insertions, 228 deletions
diff --git a/nova/api/mapper.py b/nova/api/mapper.py new file mode 100644 index 000000000..cd26e06ee --- /dev/null +++ b/nova/api/mapper.py @@ -0,0 +1,76 @@ +# 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 wsgi +from nova import flags +from nova import log as logging +from nova import wsgi as base_wsgi + + +LOG = logging.getLogger('nova.api.openstack.compute') +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) diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py index e69de29bb..dfc174a58 100644 --- a/nova/api/openstack/__init__.py +++ b/nova/api/openstack/__init__.py @@ -0,0 +1,69 @@ +# 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 wsgi +from nova import flags +from nova import log as logging +from nova import wsgi as base_wsgi + + +LOG = logging.getLogger('nova.api.openstack') + + +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) diff --git a/nova/api/openstack/v2/auth.py b/nova/api/openstack/auth.py index ba5fb603f..9a0432d51 100644 --- a/nova/api/openstack/v2/auth.py +++ b/nova/api/openstack/auth.py @@ -32,7 +32,7 @@ from nova import log as logging from nova import utils from nova import wsgi as base_wsgi -LOG = logging.getLogger('nova.api.openstack.v2.auth') +LOG = logging.getLogger('nova.api.openstack.compute.auth') FLAGS = flags.FLAGS flags.DECLARE('use_forwarded_for', 'nova.api.auth') diff --git a/nova/api/openstack/v2/__init__.py b/nova/api/openstack/compute/__init__.py index c211cd2f9..2f6e92a42 100644 --- a/nova/api/openstack/v2/__init__.py +++ b/nova/api/openstack/compute/__init__.py @@ -24,23 +24,24 @@ import routes import webob.dec import webob.exc -from nova.api.openstack.v2 import consoles -from nova.api.openstack.v2 import extensions -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 versions +import nova.api.openstack +from nova.api.openstack.compute import consoles +from nova.api.openstack.compute import extensions +from nova.api.openstack.compute import flavors +from nova.api.openstack.compute import images +from nova.api.openstack.compute import image_metadata +from nova.api.openstack.compute import ips +from nova.api.openstack.compute import limits +from nova.api.openstack.compute import servers +from nova.api.openstack.compute import server_metadata +from nova.api.openstack.compute import versions 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') +LOG = logging.getLogger('nova.api.openstack.compute') FLAGS = flags.FLAGS flags.DEFINE_bool('allow_admin_api', False, @@ -50,43 +51,6 @@ flags.DEFINE_bool('allow_instance_snapshots', '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 @@ -102,7 +66,7 @@ class APIRouter(base_wsgi.Router): if ext_mgr is None: ext_mgr = extensions.ExtensionManager() - mapper = ProjectMapper() + mapper = nova.api.openstack.ProjectMapper() self._setup_routes(mapper) self._setup_ext_routes(mapper, ext_mgr) super(APIRouter, self).__init__(mapper) diff --git a/nova/api/openstack/v2/consoles.py b/nova/api/openstack/compute/consoles.py index e9eee4c75..e9eee4c75 100644 --- a/nova/api/openstack/v2/consoles.py +++ b/nova/api/openstack/compute/consoles.py diff --git a/nova/api/openstack/compute/contrib/__init__.py b/nova/api/openstack/compute/contrib/__init__.py new file mode 100644 index 000000000..2713a82f4 --- /dev/null +++ b/nova/api/openstack/compute/contrib/__init__.py @@ -0,0 +1,32 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# 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. + +"""Contrib contains extensions that are shipped with nova. + +It can't be called 'extensions' because that causes namespacing problems. + +""" + +from nova import log as logging +from nova.api.openstack import extensions + + +LOG = logging.getLogger('nova.api.openstack.compute.contrib') + + +def standard_extensions(ext_mgr): + extensions.load_standard_extensions(ext_mgr, LOG, __path__, __package__) diff --git a/nova/api/openstack/v2/contrib/accounts.py b/nova/api/openstack/compute/contrib/accounts.py index 9bfff31d7..9253c037d 100644 --- a/nova/api/openstack/v2/contrib/accounts.py +++ b/nova/api/openstack/compute/contrib/accounts.py @@ -15,7 +15,7 @@ import webob.exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.auth import manager @@ -25,7 +25,7 @@ from nova import log as logging FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack.v2.contrib.accounts') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.accounts') class AccountTemplate(xmlutil.TemplateBuilder): diff --git a/nova/api/openstack/v2/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py index 5479f88c4..dedef3061 100644 --- a/nova/api/openstack/v2/contrib/admin_actions.py +++ b/nova/api/openstack/compute/contrib/admin_actions.py @@ -19,7 +19,7 @@ import webob from webob import exc from nova.api.openstack import common -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import compute from nova import exception from nova import flags @@ -28,7 +28,7 @@ from nova.scheduler import api as scheduler_api FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.v2.contrib.admin_actions") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.admin_actions") class Admin_actions(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/cloudpipe.py b/nova/api/openstack/compute/contrib/cloudpipe.py index 9327e3987..17bfa810b 100644 --- a/nova/api/openstack/v2/contrib/cloudpipe.py +++ b/nova/api/openstack/compute/contrib/cloudpipe.py @@ -18,7 +18,7 @@ import os from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.auth import manager from nova.cloudpipe import pipelib from nova import compute @@ -31,7 +31,7 @@ from nova import utils FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.v2.contrib.cloudpipe") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.cloudpipe") class CloudpipeTemplate(xmlutil.TemplateBuilder): diff --git a/nova/api/openstack/v2/contrib/console_output.py b/nova/api/openstack/compute/contrib/console_output.py index 0c9196398..a27d8663b 100644 --- a/nova/api/openstack/v2/contrib/console_output.py +++ b/nova/api/openstack/compute/contrib/console_output.py @@ -21,10 +21,10 @@ import webob from nova import compute from nova import exception from nova import log as logging -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions -LOG = logging.getLogger('nova.api.openstack.v2.contrib.console_output') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.console_output') class Console_output(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/createserverext.py b/nova/api/openstack/compute/contrib/createserverext.py index 70fe2796f..25b53a0d6 100644 --- a/nova/api/openstack/v2/contrib/createserverext.py +++ b/nova/api/openstack/compute/contrib/createserverext.py @@ -14,9 +14,9 @@ # License for the specific language governing permissions and limitations # under the License -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 extensions +from nova.api.openstack.compute import servers +from nova.api.openstack.compute import views from nova.api.openstack import wsgi diff --git a/nova/api/openstack/v2/contrib/deferred_delete.py b/nova/api/openstack/compute/contrib/deferred_delete.py index 0b7c60073..312c22c80 100644 --- a/nova/api/openstack/v2/contrib/deferred_delete.py +++ b/nova/api/openstack/compute/contrib/deferred_delete.py @@ -18,14 +18,14 @@ import webob from nova.api.openstack import common -from nova.api.openstack.v2 import extensions -from nova.api.openstack.v2 import servers +from nova.api.openstack import extensions +from nova.api.openstack.compute import servers from nova import compute from nova import exception from nova import log as logging -LOG = logging.getLogger("nova.api.openstack.v2.contrib.deferred-delete") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.deferred-delete") class Deferred_delete(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/disk_config.py b/nova/api/openstack/compute/contrib/disk_config.py index 7ce24a3fd..392291652 100644 --- a/nova/api/openstack/v2/contrib/disk_config.py +++ b/nova/api/openstack/compute/contrib/disk_config.py @@ -20,7 +20,7 @@ from xml.dom import minidom from webob import exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import xmlutil from nova import compute from nova import db diff --git a/nova/api/openstack/v2/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py index a3b0410f6..7f9301b93 100644 --- a/nova/api/openstack/v2/contrib/extended_status.py +++ b/nova/api/openstack/compute/contrib/extended_status.py @@ -16,7 +16,7 @@ from webob import exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import xmlutil from nova import compute from nova import exception @@ -25,7 +25,7 @@ from nova import log as logging FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.v2.contrib.extendedstatus") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.extendedstatus") class Extended_status(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/flavorextradata.py b/nova/api/openstack/compute/contrib/flavorextradata.py index 462ad1aba..bf6fa8040 100644 --- a/nova/api/openstack/v2/contrib/flavorextradata.py +++ b/nova/api/openstack/compute/contrib/flavorextradata.py @@ -24,7 +24,7 @@ attributes. This extension adds to that list: swap """ -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions class Flavorextradata(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/flavorextraspecs.py b/nova/api/openstack/compute/contrib/flavorextraspecs.py index cb5b572fa..eafea5d1f 100644 --- a/nova/api/openstack/v2/contrib/flavorextraspecs.py +++ b/nova/api/openstack/compute/contrib/flavorextraspecs.py @@ -21,7 +21,7 @@ from webob import exc from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import db from nova import exception diff --git a/nova/api/openstack/v2/contrib/floating_ip_dns.py b/nova/api/openstack/compute/contrib/floating_ip_dns.py index de1a0a27e..032d5bd7e 100644 --- a/nova/api/openstack/v2/contrib/floating_ip_dns.py +++ b/nova/api/openstack/compute/contrib/floating_ip_dns.py @@ -20,13 +20,13 @@ import webob from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import exception from nova import log as logging from nova import network -LOG = logging.getLogger('nova.api.openstack.v2.contrib.floating_ip_dns') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ip_dns') def make_dns_entry(elem): diff --git a/nova/api/openstack/v2/contrib/floating_ip_pools.py b/nova/api/openstack/compute/contrib/floating_ip_pools.py index 9d6386f25..01b9a3645 100644 --- a/nova/api/openstack/v2/contrib/floating_ip_pools.py +++ b/nova/api/openstack/compute/contrib/floating_ip_pools.py @@ -16,12 +16,12 @@ from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import log as logging from nova import network -LOG = logging.getLogger('nova.api.openstack.v2.contrib.floating_ip_poolss') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ip_pools') def _translate_floating_ip_view(pool): diff --git a/nova/api/openstack/v2/contrib/floating_ips.py b/nova/api/openstack/compute/contrib/floating_ips.py index 3a6f4ee34..2400f6c83 100644 --- a/nova/api/openstack/v2/contrib/floating_ips.py +++ b/nova/api/openstack/compute/contrib/floating_ips.py @@ -21,7 +21,7 @@ import webob from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import compute from nova import exception from nova import log as logging @@ -29,7 +29,7 @@ from nova import network from nova import rpc -LOG = logging.getLogger('nova.api.openstack.v2.contrib.floating_ips') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.floating_ips') def make_float_ip(elem): diff --git a/nova/api/openstack/v2/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py index 2bb61696e..66dd64def 100644 --- a/nova/api/openstack/v2/contrib/hosts.py +++ b/nova/api/openstack/compute/contrib/hosts.py @@ -21,7 +21,7 @@ from xml.parsers import expat from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import compute from nova import exception from nova import flags @@ -29,7 +29,7 @@ from nova import log as logging from nova.scheduler import api as scheduler_api -LOG = logging.getLogger("nova.api.openstack.v2.contrib.hosts") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.hosts") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/v2/contrib/keypairs.py b/nova/api/openstack/compute/contrib/keypairs.py index 2dc9b063d..5ac205df5 100644 --- a/nova/api/openstack/v2/contrib/keypairs.py +++ b/nova/api/openstack/compute/contrib/keypairs.py @@ -26,7 +26,7 @@ from webob import exc from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import crypto from nova import db from nova import exception diff --git a/nova/api/openstack/v2/contrib/multinic.py b/nova/api/openstack/compute/contrib/multinic.py index 6719fb18a..18b95e63d 100644 --- a/nova/api/openstack/v2/contrib/multinic.py +++ b/nova/api/openstack/compute/contrib/multinic.py @@ -18,13 +18,13 @@ import webob from webob import exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import compute from nova import exception from nova import log as logging -LOG = logging.getLogger("nova.api.openstack.v2.contrib.multinic") +LOG = logging.getLogger("nova.api.openstack.compute.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/v2/contrib/networks.py b/nova/api/openstack/compute/contrib/networks.py index 4a96e534f..f2381a19d 100644 --- a/nova/api/openstack/v2/contrib/networks.py +++ b/nova/api/openstack/compute/contrib/networks.py @@ -19,7 +19,7 @@ from webob import exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import exception from nova import flags from nova import log as logging @@ -27,7 +27,7 @@ import nova.network.api FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack.v2.contrib.networks') +LOG = logging.getLogger('nova.api.openstack.compute.contrib.networks') def network_dict(network): diff --git a/nova/api/openstack/v2/contrib/quotas.py b/nova/api/openstack/compute/contrib/quotas.py index 191553a02..5e4a20568 100644 --- a/nova/api/openstack/v2/contrib/quotas.py +++ b/nova/api/openstack/compute/contrib/quotas.py @@ -19,7 +19,7 @@ import webob from nova.api.openstack import wsgi from nova.api.openstack import xmlutil -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova import db from nova import exception from nova import quota diff --git a/nova/api/openstack/v2/contrib/rescue.py b/nova/api/openstack/compute/contrib/rescue.py index 20c18028d..0ea77cc6a 100644 --- a/nova/api/openstack/v2/contrib/rescue.py +++ b/nova/api/openstack/compute/contrib/rescue.py @@ -17,7 +17,7 @@ import webob from webob import exc -from nova.api.openstack.v2 import extensions as exts +from nova.api.openstack import extensions as exts from nova import compute from nova import exception from nova import flags @@ -26,7 +26,7 @@ from nova import utils FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.v2.contrib.rescue") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.rescue") class Rescue(exts.ExtensionDescriptor): diff --git a/nova/api/openstack/v2/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py index f4abbcd51..f0d3dfe16 100644 --- a/nova/api/openstack/v2/contrib/security_groups.py +++ b/nova/api/openstack/compute/contrib/security_groups.py @@ -22,7 +22,7 @@ from webob import exc import webob from nova.api.openstack import common -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -33,7 +33,7 @@ from nova import log as logging from nova import utils -LOG = logging.getLogger("nova.api.openstack.v2.contrib.security_groups") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.security_groups") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/v2/contrib/server_action_list.py b/nova/api/openstack/compute/contrib/server_action_list.py index 90573043e..436758572 100644 --- a/nova/api/openstack/v2/contrib/server_action_list.py +++ b/nova/api/openstack/compute/contrib/server_action_list.py @@ -15,7 +15,7 @@ import webob.exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute diff --git a/nova/api/openstack/v2/contrib/server_diagnostics.py b/nova/api/openstack/compute/contrib/server_diagnostics.py index daeda5081..11d1affaf 100644 --- a/nova/api/openstack/v2/contrib/server_diagnostics.py +++ b/nova/api/openstack/compute/contrib/server_diagnostics.py @@ -15,7 +15,7 @@ import webob.exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute diff --git a/nova/api/openstack/v2/contrib/simple_tenant_usage.py b/nova/api/openstack/compute/contrib/simple_tenant_usage.py index 7b07dfae1..f34581f6c 100644 --- a/nova/api/openstack/v2/contrib/simple_tenant_usage.py +++ b/nova/api/openstack/compute/contrib/simple_tenant_usage.py @@ -20,7 +20,7 @@ import urlparse import webob -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.compute import api diff --git a/nova/api/openstack/v2/contrib/users.py b/nova/api/openstack/compute/contrib/users.py index e24c7c068..55dba02e4 100644 --- a/nova/api/openstack/v2/contrib/users.py +++ b/nova/api/openstack/compute/contrib/users.py @@ -16,7 +16,7 @@ from webob import exc from nova.api.openstack import common -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.auth import manager diff --git a/nova/api/openstack/v2/contrib/virtual_interfaces.py b/nova/api/openstack/compute/contrib/virtual_interfaces.py index 401c7133e..ea37c4d97 100644 --- a/nova/api/openstack/v2/contrib/virtual_interfaces.py +++ b/nova/api/openstack/compute/contrib/virtual_interfaces.py @@ -16,14 +16,15 @@ """The virtual interfaces extension.""" from nova.api.openstack import common -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import log as logging from nova import network -LOG = logging.getLogger("nova.api.openstack.v2.contrib.virtual_interfaces") +LOG = logging.getLogger("nova.api.openstack.compute." + "contrib.virtual_interfaces") vif_nsmap = {None: wsgi.XMLNS_V11} diff --git a/nova/api/openstack/v2/contrib/virtual_storage_arrays.py b/nova/api/openstack/compute/contrib/virtual_storage_arrays.py index 0dee3f1b4..39edd155b 100644 --- a/nova/api/openstack/v2/contrib/virtual_storage_arrays.py +++ b/nova/api/openstack/compute/contrib/virtual_storage_arrays.py @@ -22,9 +22,9 @@ import webob from webob import exc 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.compute.contrib import volumes +from nova.api.openstack import extensions +from nova.api.openstack.compute import servers from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -40,7 +40,7 @@ from nova import volume FLAGS = flags.FLAGS -LOG = logging.getLogger("nova.api.openstack.v2.contrib.vsa") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.vsa") def _vsa_view(context, vsa, details=False, instances=None): diff --git a/nova/api/openstack/v2/contrib/volumes.py b/nova/api/openstack/compute/contrib/volumes.py index 0ca50b288..972c000ef 100644 --- a/nova/api/openstack/v2/contrib/volumes.py +++ b/nova/api/openstack/compute/contrib/volumes.py @@ -19,8 +19,8 @@ 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.api.openstack import extensions +from nova.api.openstack.compute import servers from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -31,7 +31,7 @@ from nova import volume from nova.volume import volume_types -LOG = logging.getLogger("nova.api.openstack.v2.contrib.volumes") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.volumes") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/v2/contrib/volumetypes.py b/nova/api/openstack/compute/contrib/volumetypes.py index 231c86b1b..bf249f3f8 100644 --- a/nova/api/openstack/v2/contrib/volumetypes.py +++ b/nova/api/openstack/compute/contrib/volumetypes.py @@ -19,7 +19,7 @@ from webob import exc -from nova.api.openstack.v2 import extensions +from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import db diff --git a/nova/api/openstack/v2/contrib/zones.py b/nova/api/openstack/compute/contrib/zones.py index adbc6580f..28e6f0772 100644 --- a/nova/api/openstack/v2/contrib/zones.py +++ b/nova/api/openstack/compute/contrib/zones.py @@ -20,8 +20,8 @@ import json from nova.api.openstack import common -from nova.api.openstack.v2 import servers -from nova.api.openstack.v2 import extensions +from nova.api.openstack.compute import servers +from nova.api.openstack import extensions from nova.api.openstack import xmlutil from nova.api.openstack import wsgi from nova.compute import api as compute @@ -32,7 +32,7 @@ from nova import log as logging import nova.scheduler.api -LOG = logging.getLogger("nova.api.openstack.v2.contrib.zones") +LOG = logging.getLogger("nova.api.openstack.compute.contrib.zones") FLAGS = flags.FLAGS diff --git a/nova/api/openstack/compute/extensions.py b/nova/api/openstack/compute/extensions.py new file mode 100644 index 000000000..39849e802 --- /dev/null +++ b/nova/api/openstack/compute/extensions.py @@ -0,0 +1,45 @@ +# 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. + +from nova.api.openstack import extensions as base_extensions +from nova import flags +from nova import log as logging + + +LOG = logging.getLogger('nova.api.openstack.compute.extensions') +FLAGS = flags.FLAGS + + +class ExtensionManager(base_extensions.ExtensionManager): + def __new__(cls): + if cls._ext_mgr is None: + LOG.audit(_('Initializing extension manager.')) + + cls._ext_mgr = super(ExtensionManager, cls).__new__(cls) + + cls.cls_list = FLAGS.osapi_compute_extension + cls._ext_mgr.extensions = {} + cls._ext_mgr._load_extensions() + + return cls._ext_mgr + + +class ExtensionMiddleware(base_extensions.ExtensionMiddleware): + def __init__(self, application, ext_mgr=None): + if not ext_mgr: + ext_mgr = ExtensionManager() + super(ExtensionMiddleware, self).__init__(application, ext_mgr) diff --git a/nova/api/openstack/v2/flavors.py b/nova/api/openstack/compute/flavors.py index 21c2a8120..b5212e703 100644 --- a/nova/api/openstack/v2/flavors.py +++ b/nova/api/openstack/compute/flavors.py @@ -17,7 +17,7 @@ import webob -from nova.api.openstack.v2.views import flavors as flavors_view +from nova.api.openstack.compute.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/v2/image_metadata.py b/nova/api/openstack/compute/image_metadata.py index 1e29d23ce..1e29d23ce 100644 --- a/nova/api/openstack/v2/image_metadata.py +++ b/nova/api/openstack/compute/image_metadata.py diff --git a/nova/api/openstack/v2/images.py b/nova/api/openstack/compute/images.py index 96a2275e6..194c5071e 100644 --- a/nova/api/openstack/v2/images.py +++ b/nova/api/openstack/compute/images.py @@ -16,7 +16,7 @@ import webob.exc from nova.api.openstack import common -from nova.api.openstack.v2.views import images as views_images +from nova.api.openstack.compute.views import images as views_images from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -26,7 +26,7 @@ import nova.image from nova import log -LOG = log.getLogger('nova.api.openstack.v2.images') +LOG = log.getLogger('nova.api.openstack.compute.images') FLAGS = flags.FLAGS SUPPORTED_FILTERS = { diff --git a/nova/api/openstack/v2/ips.py b/nova/api/openstack/compute/ips.py index 3dc9cf928..ec107914a 100644 --- a/nova/api/openstack/v2/ips.py +++ b/nova/api/openstack/compute/ips.py @@ -19,14 +19,14 @@ 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.compute.views import addresses as view_addresses from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import log as logging from nova import flags -LOG = logging.getLogger('nova.api.openstack.v2.ips') +LOG = logging.getLogger('nova.api.openstack.compute.ips') FLAGS = flags.FLAGS diff --git a/nova/api/openstack/v2/limits.py b/nova/api/openstack/compute/limits.py index e1f5ff836..0a1b80057 100644 --- a/nova/api/openstack/v2/limits.py +++ b/nova/api/openstack/compute/limits.py @@ -28,7 +28,7 @@ import time from webob.dec import wsgify import webob.exc -from nova.api.openstack.v2.views import limits as limits_views +from nova.api.openstack.compute.views import limits as limits_views from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import quota diff --git a/nova/api/openstack/v2/ratelimiting/__init__.py b/nova/api/openstack/compute/ratelimiting/__init__.py index 78dc465a7..78dc465a7 100644 --- a/nova/api/openstack/v2/ratelimiting/__init__.py +++ b/nova/api/openstack/compute/ratelimiting/__init__.py diff --git a/nova/api/openstack/v2/schemas/atom-link.rng b/nova/api/openstack/compute/schemas/atom-link.rng index edba5eee6..edba5eee6 100644 --- a/nova/api/openstack/v2/schemas/atom-link.rng +++ b/nova/api/openstack/compute/schemas/atom-link.rng diff --git a/nova/api/openstack/v2/schemas/atom.rng b/nova/api/openstack/compute/schemas/atom.rng index c2df4e410..c2df4e410 100644 --- a/nova/api/openstack/v2/schemas/atom.rng +++ b/nova/api/openstack/compute/schemas/atom.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/addresses.rng b/nova/api/openstack/compute/schemas/v1.1/addresses.rng index b498e8a63..b498e8a63 100644 --- a/nova/api/openstack/v2/schemas/v1.1/addresses.rng +++ b/nova/api/openstack/compute/schemas/v1.1/addresses.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/extension.rng b/nova/api/openstack/compute/schemas/v1.1/extension.rng index 336659755..336659755 100644 --- a/nova/api/openstack/v2/schemas/v1.1/extension.rng +++ b/nova/api/openstack/compute/schemas/v1.1/extension.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/extensions.rng b/nova/api/openstack/compute/schemas/v1.1/extensions.rng index 4d8bff646..4d8bff646 100644 --- a/nova/api/openstack/v2/schemas/v1.1/extensions.rng +++ b/nova/api/openstack/compute/schemas/v1.1/extensions.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/flavor.rng b/nova/api/openstack/compute/schemas/v1.1/flavor.rng index 08746ce3d..08746ce3d 100644 --- a/nova/api/openstack/v2/schemas/v1.1/flavor.rng +++ b/nova/api/openstack/compute/schemas/v1.1/flavor.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/flavors.rng b/nova/api/openstack/compute/schemas/v1.1/flavors.rng index b7a3acc01..b7a3acc01 100644 --- a/nova/api/openstack/v2/schemas/v1.1/flavors.rng +++ b/nova/api/openstack/compute/schemas/v1.1/flavors.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/flavors_index.rng b/nova/api/openstack/compute/schemas/v1.1/flavors_index.rng index d1a4fedb1..d1a4fedb1 100644 --- a/nova/api/openstack/v2/schemas/v1.1/flavors_index.rng +++ b/nova/api/openstack/compute/schemas/v1.1/flavors_index.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/image.rng b/nova/api/openstack/compute/schemas/v1.1/image.rng index 505081fba..505081fba 100644 --- a/nova/api/openstack/v2/schemas/v1.1/image.rng +++ b/nova/api/openstack/compute/schemas/v1.1/image.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/images.rng b/nova/api/openstack/compute/schemas/v1.1/images.rng index 064d4d9cc..064d4d9cc 100644 --- a/nova/api/openstack/v2/schemas/v1.1/images.rng +++ b/nova/api/openstack/compute/schemas/v1.1/images.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/images_index.rng b/nova/api/openstack/compute/schemas/v1.1/images_index.rng index 3db0b2672..3db0b2672 100644 --- a/nova/api/openstack/v2/schemas/v1.1/images_index.rng +++ b/nova/api/openstack/compute/schemas/v1.1/images_index.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/limits.rng b/nova/api/openstack/compute/schemas/v1.1/limits.rng index 1af8108ec..1af8108ec 100644 --- a/nova/api/openstack/v2/schemas/v1.1/limits.rng +++ b/nova/api/openstack/compute/schemas/v1.1/limits.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/metadata.rng b/nova/api/openstack/compute/schemas/v1.1/metadata.rng index b2f5d702a..b2f5d702a 100644 --- a/nova/api/openstack/v2/schemas/v1.1/metadata.rng +++ b/nova/api/openstack/compute/schemas/v1.1/metadata.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/server.rng b/nova/api/openstack/compute/schemas/v1.1/server.rng index 07fa16daa..07fa16daa 100644 --- a/nova/api/openstack/v2/schemas/v1.1/server.rng +++ b/nova/api/openstack/compute/schemas/v1.1/server.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/servers.rng b/nova/api/openstack/compute/schemas/v1.1/servers.rng index 4e2bb8853..4e2bb8853 100644 --- a/nova/api/openstack/v2/schemas/v1.1/servers.rng +++ b/nova/api/openstack/compute/schemas/v1.1/servers.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/servers_index.rng b/nova/api/openstack/compute/schemas/v1.1/servers_index.rng index 023e4b66a..023e4b66a 100644 --- a/nova/api/openstack/v2/schemas/v1.1/servers_index.rng +++ b/nova/api/openstack/compute/schemas/v1.1/servers_index.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/version.rng b/nova/api/openstack/compute/schemas/v1.1/version.rng index ae76270ba..ae76270ba 100644 --- a/nova/api/openstack/v2/schemas/v1.1/version.rng +++ b/nova/api/openstack/compute/schemas/v1.1/version.rng diff --git a/nova/api/openstack/v2/schemas/v1.1/versions.rng b/nova/api/openstack/compute/schemas/v1.1/versions.rng index 8b2cc7f71..8b2cc7f71 100644 --- a/nova/api/openstack/v2/schemas/v1.1/versions.rng +++ b/nova/api/openstack/compute/schemas/v1.1/versions.rng diff --git a/nova/api/openstack/v2/server_metadata.py b/nova/api/openstack/compute/server_metadata.py index 52a90f96e..52a90f96e 100644 --- a/nova/api/openstack/v2/server_metadata.py +++ b/nova/api/openstack/compute/server_metadata.py diff --git a/nova/api/openstack/v2/servers.py b/nova/api/openstack/compute/servers.py index c2655a73e..60b85f591 100644 --- a/nova/api/openstack/v2/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -22,8 +22,8 @@ from webob import exc import webob from nova.api.openstack import common -from nova.api.openstack.v2 import ips -from nova.api.openstack.v2.views import servers as views_servers +from nova.api.openstack.compute import ips +from nova.api.openstack.compute.views import servers as views_servers from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import compute @@ -36,7 +36,7 @@ from nova.scheduler import api as scheduler_api from nova import utils -LOG = logging.getLogger('nova.api.openstack.v2.servers') +LOG = logging.getLogger('nova.api.openstack.compute.servers') FLAGS = flags.FLAGS diff --git a/nova/api/openstack/v2/versions.py b/nova/api/openstack/compute/versions.py index 45b84f7c2..ddc31e9f0 100644 --- a/nova/api/openstack/v2/versions.py +++ b/nova/api/openstack/compute/versions.py @@ -19,7 +19,7 @@ from datetime import datetime from lxml import etree -from nova.api.openstack.v2.views import versions as views_versions +from nova.api.openstack.compute.views import versions as views_versions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil diff --git a/nova/api/openstack/v2/views/__init__.py b/nova/api/openstack/compute/views/__init__.py index e69de29bb..e69de29bb 100644 --- a/nova/api/openstack/v2/views/__init__.py +++ b/nova/api/openstack/compute/views/__init__.py diff --git a/nova/api/openstack/v2/views/addresses.py b/nova/api/openstack/compute/views/addresses.py index 6f518b11a..776ba9e59 100644 --- a/nova/api/openstack/v2/views/addresses.py +++ b/nova/api/openstack/compute/views/addresses.py @@ -23,7 +23,7 @@ from nova import log as logging FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.api.openstack.v2.views.addresses') +LOG = logging.getLogger('nova.api.openstack.compute.views.addresses') class ViewBuilder(common.ViewBuilder): diff --git a/nova/api/openstack/v2/views/flavors.py b/nova/api/openstack/compute/views/flavors.py index 64284e406..64284e406 100644 --- a/nova/api/openstack/v2/views/flavors.py +++ b/nova/api/openstack/compute/views/flavors.py diff --git a/nova/api/openstack/v2/views/images.py b/nova/api/openstack/compute/views/images.py index c4cfe8031..c4cfe8031 100644 --- a/nova/api/openstack/v2/views/images.py +++ b/nova/api/openstack/compute/views/images.py diff --git a/nova/api/openstack/v2/views/limits.py b/nova/api/openstack/compute/views/limits.py index cff6781be..cff6781be 100644 --- a/nova/api/openstack/v2/views/limits.py +++ b/nova/api/openstack/compute/views/limits.py diff --git a/nova/api/openstack/v2/views/servers.py b/nova/api/openstack/compute/views/servers.py index 859bd48ab..6a1622a66 100644 --- a/nova/api/openstack/v2/views/servers.py +++ b/nova/api/openstack/compute/views/servers.py @@ -19,14 +19,14 @@ import hashlib from nova.api.openstack import common -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.compute.views import addresses as views_addresses +from nova.api.openstack.compute.views import flavors as views_flavors +from nova.api.openstack.compute.views import images as views_images from nova import log as logging from nova import utils -LOG = logging.getLogger('nova.api.openstack.v2.views.servers') +LOG = logging.getLogger('nova.api.openstack.compute.views.servers') class ViewBuilder(common.ViewBuilder): diff --git a/nova/api/openstack/v2/views/versions.py b/nova/api/openstack/compute/views/versions.py index cb2fd9f4a..cb2fd9f4a 100644 --- a/nova/api/openstack/v2/views/versions.py +++ b/nova/api/openstack/compute/views/versions.py diff --git a/nova/api/openstack/v2/extensions.py b/nova/api/openstack/extensions.py index 0aa3146a9..6c49e8ace 100644 --- a/nova/api/openstack/v2/extensions.py +++ b/nova/api/openstack/extensions.py @@ -16,11 +16,12 @@ # License for the specific language governing permissions and limitations # under the License. +import os import routes import webob.dec import webob.exc -import nova.api.openstack.v2 +import nova.api.openstack from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import exception @@ -30,7 +31,7 @@ from nova import utils from nova import wsgi as base_wsgi -LOG = logging.getLogger('nova.api.openstack.v2.extensions') +LOG = logging.getLogger('nova.api.openstack.extensions') FLAGS = flags.FLAGS @@ -326,7 +327,7 @@ class ExtensionMiddleware(base_wsgi.Middleware): ext_mgr = ExtensionManager() self.ext_mgr = ext_mgr - mapper = nova.api.openstack.v2.ProjectMapper() + mapper = nova.api.openstack.ProjectMapper() # extended actions action_resources = self._action_ext_resources(application, ext_mgr, @@ -388,17 +389,6 @@ class ExtensionManager(object): def reset(cls): cls._ext_mgr = None - def __new__(cls): - if cls._ext_mgr is None: - LOG.audit(_('Initializing extension manager.')) - - cls._ext_mgr = super(ExtensionManager, cls).__new__(cls) - - cls._ext_mgr.extensions = {} - cls._ext_mgr._load_extensions() - - return cls._ext_mgr - def register(self, ext): # Do nothing if the extension doesn't check out if not self._check_extension(ext): @@ -483,7 +473,6 @@ class ExtensionManager(object): LOG.debug(_("Loading extension %s"), ext_factory) # Load the factory - factory = utils.import_class(ext_factory) # Call it @@ -493,7 +482,7 @@ class ExtensionManager(object): def _load_extensions(self): """Load extensions specified on the command line.""" - extensions = list(FLAGS.osapi_extension) + extensions = list(self.cls_list) for ext_factory in extensions: try: @@ -573,3 +562,62 @@ def wrap_errors(fn): except Exception, e: raise webob.exc.HTTPInternalServerError() return wrapped + + +def load_standard_extensions(ext_mgr, logger, path, package): + """Registers all standard API extensions.""" + + # Walk through all the modules in our directory... + our_dir = path[0] + for dirpath, dirnames, filenames in os.walk(our_dir): + # Compute the relative package name from the dirpath + relpath = os.path.relpath(dirpath, our_dir) + if relpath == '.': + relpkg = '' + else: + relpkg = '.%s' % '.'.join(relpath.split(os.sep)) + + # Now, consider each file in turn, only considering .py files + for fname in filenames: + root, ext = os.path.splitext(fname) + + # Skip __init__ and anything that's not .py + if ext != '.py' or root == '__init__': + continue + + # Try loading it + classname = ("%s%s.%s.%s%s" % + (package, relpkg, root, + root[0].upper(), root[1:])) + try: + ext_mgr.load_extension(classname) + except Exception as exc: + logger.warn(_('Failed to load extension %(classname)s: ' + '%(exc)s') % locals()) + + # Now, let's consider any subdirectories we may have... + subdirs = [] + for dname in dirnames: + # Skip it if it does not have __init__.py + if not os.path.exists(os.path.join(dirpath, dname, + '__init__.py')): + continue + + # If it has extension(), delegate... + ext_name = ("%s%s.%s.extension" % + (package, relpkg, dname)) + try: + ext = utils.import_class(ext_name) + except exception.ClassNotFound: + # extension() doesn't exist on it, so we'll explore + # the directory for ourselves + subdirs.append(dname) + else: + try: + ext(ext_mgr) + except Exception as exc: + logger.warn(_('Failed to load extension %(ext_name)s: ' + '%(exc)s') % locals()) + + # Update the list of directories we'll explore... + dirnames[:] = subdirs diff --git a/nova/api/openstack/v2/urlmap.py b/nova/api/openstack/urlmap.py index bae69198e..825a12af2 100644 --- a/nova/api/openstack/v2/urlmap.py +++ b/nova/api/openstack/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.v2.map') +LOG = logging.getLogger('nova.api.openstack.compute.map') def unquote_header_value(value): diff --git a/nova/api/openstack/v2/contrib/__init__.py b/nova/api/openstack/v2/contrib/__init__.py deleted file mode 100644 index d361dac9c..000000000 --- a/nova/api/openstack/v2/contrib/__init__.py +++ /dev/null @@ -1,90 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 Justin Santa Barbara -# 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. - -"""Contrib contains extensions that are shipped with nova. - -It can't be called 'extensions' because that causes namespacing problems. - -""" - -import os - -from nova import exception -from nova import log as logging -from nova import utils - - -LOG = logging.getLogger('nova.api.openstack.v2.contrib') - - -def standard_extensions(ext_mgr): - """Registers all standard API extensions.""" - - # Walk through all the modules in our directory... - our_dir = __path__[0] - for dirpath, dirnames, filenames in os.walk(our_dir): - # Compute the relative package name from the dirpath - relpath = os.path.relpath(dirpath, our_dir) - if relpath == '.': - relpkg = '' - else: - relpkg = '.%s' % '.'.join(relpath.split(os.sep)) - - # Now, consider each file in turn, only considering .py files - for fname in filenames: - root, ext = os.path.splitext(fname) - - # Skip __init__ and anything that's not .py - if ext != '.py' or root == '__init__': - continue - - # Try loading it - classname = ("%s%s.%s.%s%s" % - (__package__, relpkg, root, - root[0].upper(), root[1:])) - try: - ext_mgr.load_extension(classname) - except Exception as exc: - LOG.warn(_('Failed to load extension %(classname)s: ' - '%(exc)s') % locals()) - - # Now, let's consider any subdirectories we may have... - subdirs = [] - for dname in dirnames: - # Skip it if it does not have __init__.py - if not os.path.exists(os.path.join(dirpath, dname, - '__init__.py')): - continue - - # If it has extension(), delegate... - ext_name = ("%s%s.%s.extension" % - (__package__, relpkg, dname)) - try: - ext = utils.import_class(ext_name) - except exception.ClassNotFound: - # extension() doesn't exist on it, so we'll explore - # the directory for ourselves - subdirs.append(dname) - else: - try: - ext(ext_mgr) - except Exception as exc: - LOG.warn(_('Failed to load extension %(ext_name)s: ' - '%(exc)s') % locals()) - - # Update the list of directories we'll explore... - dirnames[:] = subdirs diff --git a/nova/api/openstack/volume/__init__.py b/nova/api/openstack/volume/__init__.py new file mode 100644 index 000000000..075b53c29 --- /dev/null +++ b/nova/api/openstack/volume/__init__.py @@ -0,0 +1,99 @@ +# 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 Volume API. +""" + +import routes +import webob.dec +import webob.exc + +import nova.api.openstack +from nova.api.openstack.volume import extensions +from nova.api.openstack.volume import snapshots +from nova.api.openstack.volume import types +from nova.api.openstack.volume import volumes +from nova.api.openstack.volume import versions +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.volume') +FLAGS = flags.FLAGS + + +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): + if ext_mgr is None: + ext_mgr = extensions.ExtensionManager() + + mapper = nova.api.openstack.ProjectMapper() + self._setup_routes(mapper) + self._setup_ext_routes(mapper, ext_mgr) + super(APIRouter, self).__init__(mapper) + + def _setup_ext_routes(self, mapper, ext_mgr): + serializer = wsgi.ResponseSerializer( + {'application/xml': wsgi.XMLDictSerializer()}) + for resource in ext_mgr.get_resources(): + LOG.debug(_('Extended resource: %s'), + resource.collection) + if resource.serializer is None: + resource.serializer = serializer + + kargs = dict( + controller=wsgi.Resource( + resource.controller, resource.deserializer, + resource.serializer), + collection=resource.collection_actions, + member=resource.member_actions) + + if resource.parent: + kargs['parent_resource'] = resource.parent + + mapper.resource(resource.collection, resource.collection, **kargs) + + def _setup_routes(self, mapper): + mapper.connect("versions", "/", + controller=versions.create_resource(), + action='show') + + mapper.redirect("", "/") + + mapper.resource("volume", "volumes", + controller=volumes.create_resource(), + collection={'detail': 'GET'}) + + mapper.resource("type", "types", + controller=types.create_resource()) + + mapper.resource("snapshot", "snapshots", + controller=snapshots.create_resource()) diff --git a/nova/api/openstack/volume/contrib/__init__.py b/nova/api/openstack/volume/contrib/__init__.py new file mode 100644 index 000000000..58c0413ab --- /dev/null +++ b/nova/api/openstack/volume/contrib/__init__.py @@ -0,0 +1,32 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# 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. + +"""Contrib contains extensions that are shipped with nova. + +It can't be called 'extensions' because that causes namespacing problems. + +""" + +from nova import log as logging +from nova.api.openstack import extensions + + +LOG = logging.getLogger('nova.api.openstack.volume.contrib') + + +def standard_extensions(ext_mgr): + extensions.load_standard_extensions(ext_mgr, LOG, __path__, __package__) diff --git a/nova/api/openstack/volume/extensions.py b/nova/api/openstack/volume/extensions.py new file mode 100644 index 000000000..d1007629e --- /dev/null +++ b/nova/api/openstack/volume/extensions.py @@ -0,0 +1,44 @@ +# 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. + +from nova.api.openstack import extensions as base_extensions +from nova import flags +from nova import log as logging + + +LOG = logging.getLogger('nova.api.openstack.volume.extensions') +FLAGS = flags.FLAGS + + +class ExtensionManager(base_extensions.ExtensionManager): + def __new__(cls): + if cls._ext_mgr is None: + LOG.audit(_('Initializing extension manager.')) + + cls._ext_mgr = super(ExtensionManager, cls).__new__(cls) + + cls.cls_list = FLAGS.osapi_volume_extension + cls._ext_mgr.extensions = {} + cls._ext_mgr._load_extensions() + + return cls._ext_mgr + + +class ExtensionMiddleware(base_extensions.ExtensionMiddleware): + def __init__(self, application, ext_mgr=None): + ext_mgr = ExtensionManager() + super(ExtensionMiddleware, self).__init__(application, ext_mgr) diff --git a/nova/api/openstack/volume/snapshots.py b/nova/api/openstack/volume/snapshots.py new file mode 100644 index 000000000..f6ec3dc5f --- /dev/null +++ b/nova/api/openstack/volume/snapshots.py @@ -0,0 +1,183 @@ +# Copyright 2011 Justin Santa Barbara +# 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. + +"""The volumes snapshots api.""" + +from webob import exc +import webob + +from nova.api.openstack import common +from nova.api.openstack import extensions +from nova.api.openstack.compute import servers +from nova.api.openstack import wsgi +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 import volume +from nova.volume import volume_types + + +LOG = logging.getLogger("nova.api.openstack.volume.snapshots") + + +FLAGS = flags.FLAGS + + +def _translate_snapshot_detail_view(context, vol): + """Maps keys for snapshots details view.""" + + d = _translate_snapshot_summary_view(context, vol) + + # NOTE(gagupta): No additional data / lookups at the moment + return d + + +def _translate_snapshot_summary_view(context, vol): + """Maps keys for snapshots summary view.""" + d = {} + + d['id'] = vol['id'] + d['volumeId'] = vol['volume_id'] + d['status'] = vol['status'] + # NOTE(gagupta): We map volume_size as the snapshot size + d['size'] = vol['volume_size'] + d['createdAt'] = vol['created_at'] + d['displayName'] = vol['display_name'] + d['displayDescription'] = vol['display_description'] + return d + + +class SnapshotsController(object): + """The Volumes API controller for the OpenStack API.""" + + def __init__(self): + self.volume_api = volume.API() + super(SnapshotsController, self).__init__() + + def show(self, req, id): + """Return data about the given snapshot.""" + context = req.environ['nova.context'] + + try: + vol = self.volume_api.get_snapshot(context, id) + except exception.NotFound: + return exc.HTTPNotFound() + + return {'snapshot': _translate_snapshot_detail_view(context, vol)} + + def delete(self, req, id): + """Delete a snapshot.""" + context = req.environ['nova.context'] + + LOG.audit(_("Delete snapshot with id: %s"), id, context=context) + + try: + self.volume_api.delete_snapshot(context, snapshot_id=id) + except exception.NotFound: + return exc.HTTPNotFound() + return webob.Response(status_int=202) + + def index(self, req): + """Returns a summary list of snapshots.""" + return self._items(req, entity_maker=_translate_snapshot_summary_view) + + def detail(self, req): + """Returns a detailed list of snapshots.""" + return self._items(req, entity_maker=_translate_snapshot_detail_view) + + def _items(self, req, entity_maker): + """Returns a list of snapshots, transformed through entity_maker.""" + context = req.environ['nova.context'] + + snapshots = self.volume_api.get_all_snapshots(context) + limited_list = common.limited(snapshots, req) + res = [entity_maker(context, snapshot) for snapshot in limited_list] + return {'snapshots': res} + + def create(self, req, body): + """Creates a new snapshot.""" + context = req.environ['nova.context'] + + if not body: + return exc.HTTPUnprocessableEntity() + + snapshot = body['snapshot'] + volume_id = snapshot['volume_id'] + force = snapshot.get('force', False) + LOG.audit(_("Create snapshot from volume %s"), volume_id, + context=context) + + if force: + new_snapshot = self.volume_api.create_snapshot_force(context, + volume_id, + snapshot.get('display_name'), + snapshot.get('display_description')) + else: + new_snapshot = self.volume_api.create_snapshot(context, + volume_id, + snapshot.get('display_name'), + snapshot.get('display_description')) + + retval = _translate_snapshot_detail_view(context, new_snapshot) + + return {'snapshot': retval} + + +def make_snapshot(elem): + elem.set('id') + elem.set('status') + elem.set('size') + elem.set('createdAt') + elem.set('displayName') + elem.set('displayDescription') + elem.set('volumeId') + + +class SnapshotTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('snapshot', selector='snapshot') + make_snapshot(root) + return xmlutil.MasterTemplate(root, 1) + + +class SnapshotsTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('snapshots') + elem = xmlutil.SubTemplateElement(root, 'snapshot', + selector='snapshots') + make_snapshot(elem) + return xmlutil.MasterTemplate(root, 1) + + +class SnapshotSerializer(xmlutil.XMLTemplateSerializer): + def default(self): + return SnapshotTemplate() + + def index(self): + return SnapshotsTemplate() + + def detail(self): + return SnapshotsTemplate() + + +def create_resource(): + body_serializers = { + 'application/xml': SnapshotSerializer(), + } + serializer = wsgi.ResponseSerializer(body_serializers) + + return wsgi.Resource(SnapshotsController(), serializer=serializer) diff --git a/nova/api/openstack/volume/types.py b/nova/api/openstack/volume/types.py new file mode 100644 index 000000000..1c6a68b58 --- /dev/null +++ b/nova/api/openstack/volume/types.py @@ -0,0 +1,89 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Zadara Storage Inc. +# Copyright (c) 2011 OpenStack LLC. +# +# 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. + +""" The volume type & volume types extra specs extension""" + +from webob import exc + +from nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil +from nova import db +from nova import exception +from nova.volume import volume_types + + +class VolumeTypesController(object): + """ The volume types API controller for the Openstack API """ + + def index(self, req): + """ Returns the list of volume types """ + context = req.environ['nova.context'] + return volume_types.get_all_types(context) + + def show(self, req, id): + """ Return a single volume type item """ + context = req.environ['nova.context'] + + try: + vol_type = volume_types.get_volume_type(context, id) + except exception.NotFound or exception.ApiError: + raise exc.HTTPNotFound() + + return {'volume_type': vol_type} + + +def make_voltype(elem): + elem.set('id') + elem.set('name') + extra_specs = xmlutil.make_flat_dict('extra_specs', selector='extra_specs') + elem.append(extra_specs) + + +class VolumeTypeTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volume_type', selector='volume_type') + make_voltype(root) + return xmlutil.MasterTemplate(root, 1) + + +class VolumeTypesTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volume_types') + sel = lambda obj, do_raise=False: obj.values() + elem = xmlutil.SubTemplateElement(root, 'volume_type', selector=sel) + make_voltype(elem) + return xmlutil.MasterTemplate(root, 1) + + +class VolumeTypesSerializer(xmlutil.XMLTemplateSerializer): + def index(self): + return VolumeTypesTemplate() + + def default(self): + return VolumeTypeTemplate() + + +def create_resource(): + body_serializers = { + 'application/xml': VolumeTypesSerializer(), + } + serializer = wsgi.ResponseSerializer(body_serializers) + + deserializer = wsgi.RequestDeserializer() + + return wsgi.Resource(VolumeTypesController(), serializer=serializer) diff --git a/nova/api/openstack/volume/versions.py b/nova/api/openstack/volume/versions.py new file mode 100644 index 000000000..9a29e4adf --- /dev/null +++ b/nova/api/openstack/volume/versions.py @@ -0,0 +1,83 @@ +# 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. + +from datetime import datetime + +from lxml import etree + +from nova.api.openstack.compute import versions +from nova.api.openstack.volume.views import versions as views_versions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil + + +VERSIONS = { + "v1": { + "id": "v1", + "status": "CURRENT", + "updated": "2012-01-04T11:33:21Z", + "links": [ + { + "rel": "describedby", + "type": "application/pdf", + "href": "http://jorgew.github.com/block-storage-api/" + "content/os-block-storage-1.0.pdf", + }, + { + "rel": "describedby", + "type": "application/vnd.sun.wadl+xml", + #(anthony) FIXME + "href": "http://docs.rackspacecloud.com/" + "servers/api/v1.1/application.wadl", + }, + ], + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.volume+xml;version=1", + }, + { + "base": "application/json", + "type": "application/vnd.openstack.volume+json;version=1", + } + ], + } +} + + +class Versions(versions.Versions): + def dispatch(self, request, *args): + """Respond to a request for all OpenStack API versions.""" + builder = views_versions.get_view_builder(request) + if request.path == '/': + # List Versions + return builder.build_versions(VERSIONS) + else: + # Versions Multiple Choice + return builder.build_choices(VERSIONS, request) + + +class VolumeVersionV1(object): + @wsgi.serializers(xml=versions.VersionTemplate, + atom=versions.VersionAtomSerializer) + def show(self, req): + builder = views_versions.get_view_builder(req) + return builder.build_version(VERSIONS['v2.0']) + + +def create_resource(): + return wsgi.Resource(VolumeVersionV1()) diff --git a/nova/api/openstack/volume/views/__init__.py b/nova/api/openstack/volume/views/__init__.py new file mode 100644 index 000000000..d65c689a8 --- /dev/null +++ b/nova/api/openstack/volume/views/__init__.py @@ -0,0 +1,16 @@ +# 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. diff --git a/nova/api/openstack/volume/views/versions.py b/nova/api/openstack/volume/views/versions.py new file mode 100644 index 000000000..e446a4b64 --- /dev/null +++ b/nova/api/openstack/volume/views/versions.py @@ -0,0 +1,37 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010-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 copy +import os + +from nova.api.openstack.compute.views import versions as compute_views + + +def get_view_builder(req): + base_url = req.application_url + return ViewBuilder(base_url) + + +class ViewBuilder(compute_views.ViewBuilder): + def generate_href(self, path=None): + """Create an url that refers to a specific version_number.""" + version_number = 'v1' + if path: + path = path.strip('/') + return os.path.join(self.base_url, version_number, path) + else: + return os.path.join(self.base_url, version_number) + '/' diff --git a/nova/api/openstack/volume/volumes.py b/nova/api/openstack/volume/volumes.py new file mode 100644 index 000000000..5e16f4fde --- /dev/null +++ b/nova/api/openstack/volume/volumes.py @@ -0,0 +1,254 @@ +# Copyright 2011 Justin Santa Barbara +# 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. + +"""The volumes api.""" + +from webob import exc +import webob + +from nova.api.openstack import common +from nova.api.openstack.compute import servers +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 volume +from nova.volume import volume_types + + +LOG = logging.getLogger("nova.api.openstack.volume.volumes") + + +FLAGS = flags.FLAGS + + +def _translate_volume_detail_view(context, vol): + """Maps keys for volumes details view.""" + + d = _translate_volume_summary_view(context, vol) + + # No additional data / lookups at the moment + + return d + + +def _translate_volume_summary_view(context, vol): + """Maps keys for volumes summary view.""" + d = {} + + d['id'] = vol['id'] + d['status'] = vol['status'] + d['size'] = vol['size'] + d['availabilityZone'] = vol['availability_zone'] + d['createdAt'] = vol['created_at'] + + if vol['attach_status'] == 'attached': + d['attachments'] = [_translate_attachment_detail_view(context, vol)] + else: + d['attachments'] = [{}] + + d['displayName'] = vol['display_name'] + d['displayDescription'] = vol['display_description'] + + if vol['volume_type_id'] and vol.get('volume_type'): + d['volumeType'] = vol['volume_type']['name'] + else: + d['volumeType'] = vol['volume_type_id'] + + d['snapshotId'] = vol['snapshot_id'] + LOG.audit(_("vol=%s"), vol, context=context) + + if vol.get('volume_metadata'): + meta_dict = {} + for i in vol['volume_metadata']: + meta_dict[i['key']] = i['value'] + d['metadata'] = meta_dict + else: + d['metadata'] = {} + + return d + + +class VolumeController(object): + """The Volumes API controller for the OpenStack API.""" + + def __init__(self): + self.volume_api = volume.API() + super(VolumeController, self).__init__() + + def show(self, req, id): + """Return data about the given volume.""" + context = req.environ['nova.context'] + + try: + vol = self.volume_api.get(context, id) + except exception.NotFound: + raise exc.HTTPNotFound() + + return {'volume': _translate_volume_detail_view(context, vol)} + + def delete(self, req, id): + """Delete a volume.""" + context = req.environ['nova.context'] + + LOG.audit(_("Delete volume with id: %s"), id, context=context) + + try: + self.volume_api.delete(context, volume_id=id) + except exception.NotFound: + raise exc.HTTPNotFound() + return webob.Response(status_int=202) + + def index(self, req): + """Returns a summary list of volumes.""" + return self._items(req, entity_maker=_translate_volume_summary_view) + + def detail(self, req): + """Returns a detailed list of volumes.""" + return self._items(req, entity_maker=_translate_volume_detail_view) + + def _items(self, req, entity_maker): + """Returns a list of volumes, transformed through entity_maker.""" + context = req.environ['nova.context'] + + volumes = self.volume_api.get_all(context) + limited_list = common.limited(volumes, req) + res = [entity_maker(context, vol) for vol in limited_list] + return {'volumes': res} + + def create(self, req, body): + """Creates a new volume.""" + context = req.environ['nova.context'] + + if not body: + raise exc.HTTPUnprocessableEntity() + + vol = body['volume'] + size = vol['size'] + LOG.audit(_("Create volume of %s GB"), size, context=context) + + vol_type = vol.get('volume_type', None) + if vol_type: + try: + vol_type = volume_types.get_volume_type_by_name(context, + vol_type) + except exception.NotFound: + raise exc.HTTPNotFound() + + metadata = vol.get('metadata', None) + + new_volume = self.volume_api.create(context, size, + vol.get('snapshot_id'), + vol.get('display_name'), + vol.get('display_description'), + volume_type=vol_type, + metadata=metadata) + + # Work around problem that instance is lazy-loaded... + new_volume = self.volume_api.get(context, new_volume['id']) + + retval = _translate_volume_detail_view(context, new_volume) + + return {'volume': retval} + + +class VolumeAttachmentTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volumeAttachment', + selector='volumeAttachment') + make_attachment(root) + return xmlutil.MasterTemplate(root, 1) + + +class VolumeAttachmentsTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volumeAttachments') + elem = xmlutil.SubTemplateElement(root, 'volumeAttachment', + selector='volumeAttachments') + make_attachment(elem) + return xmlutil.MasterTemplate(root, 1) + + +class VolumeAttachmentSerializer(xmlutil.XMLTemplateSerializer): + def default(self): + return VolumeAttachmentTemplate() + + def index(self): + return VolumeAttachmentsTemplate() + + +def make_attachment(elem): + elem.set('id') + elem.set('serverId') + elem.set('volumeId') + elem.set('device') + + +def make_volume(elem): + elem.set('id') + elem.set('status') + elem.set('size') + elem.set('availabilityZone') + elem.set('createdAt') + elem.set('displayName') + elem.set('displayDescription') + elem.set('volumeType') + elem.set('snapshotId') + + attachments = xmlutil.SubTemplateElement(elem, 'attachments') + attachment = xmlutil.SubTemplateElement(attachments, 'attachment', + selector='attachments') + make_attachment(attachment) + + metadata = xmlutil.make_flat_dict('metadata') + elem.append(metadata) + + +class VolumeTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volume', selector='volume') + make_volume(root) + return xmlutil.MasterTemplate(root, 1) + + +class VolumesTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('volumes') + elem = xmlutil.SubTemplateElement(root, 'volume', selector='volumes') + make_volume(elem) + return xmlutil.MasterTemplate(root, 1) + + +class VolumeSerializer(xmlutil.XMLTemplateSerializer): + def default(self): + return VolumeTemplate() + + def index(self): + return VolumesTemplate() + + def detail(self): + return VolumesTemplate() + + +def create_resource(): + body_serializers = { + 'application/xml': VolumeSerializer(), + } + serializer = wsgi.ResponseSerializer(body_serializers) + + deserializer = wsgi.RequestDeserializer() + + return wsgi.Resource(VolumeController(), serializer=serializer) diff --git a/nova/api/openstack/xmlutil.py b/nova/api/openstack/xmlutil.py index 90861ad4f..4b64d4a8f 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 isinstance(xml, str): xml = etree.fromstring(xml) - base_path = 'nova/api/openstack/v2/schemas/v1.1/' + base_path = 'nova/api/openstack/compute/schemas/v1.1/' if schema_name in ('atom', 'atom-link'): - base_path = 'nova/api/openstack/v2/schemas/' + base_path = 'nova/api/openstack/compute/schemas/' schema_path = os.path.join(utils.novadir(), '%s%s.rng' % (base_path, schema_name)) schema_doc = etree.parse(schema_path) |
