summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-01-13 19:19:46 +0000
committerGerrit Code Review <review@openstack.org>2012-01-13 19:19:46 +0000
commit6c898e6abf44caa176790e9cd4505aeed145397c (patch)
tree4d9cbc1ef13d8d208284417f333e36482bdd8c26 /nova/api
parent485328e48fc7dff1ce2ebfd262c442d8f993688b (diff)
parent60ff2e3b72b5a3c9200f8fc47aac01cdb610bdcf (diff)
downloadnova-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.py76
-rw-r--r--nova/api/openstack/__init__.py69
-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__.py32
-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.py45
-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__.py90
-rw-r--r--nova/api/openstack/volume/__init__.py99
-rw-r--r--nova/api/openstack/volume/contrib/__init__.py32
-rw-r--r--nova/api/openstack/volume/extensions.py44
-rw-r--r--nova/api/openstack/volume/snapshots.py183
-rw-r--r--nova/api/openstack/volume/types.py89
-rw-r--r--nova/api/openstack/volume/versions.py83
-rw-r--r--nova/api/openstack/volume/views/__init__.py16
-rw-r--r--nova/api/openstack/volume/views/versions.py37
-rw-r--r--nova/api/openstack/volume/volumes.py254
-rw-r--r--nova/api/openstack/xmlutil.py4
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)