summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorKevin L. Mitchell <kevin.mitchell@rackspace.com>2012-01-19 16:20:04 -0600
committerKevin L. Mitchell <kevin.mitchell@rackspace.com>2012-01-19 16:20:04 -0600
commited1e6d792c5b37576640acd3e174c8a733c96b61 (patch)
treee79b7b0b317e796ae6c8188c567e1452f59f0a38 /nova/api
parent4f204a6d75f2d48608aeeafae20ab3bf8cbadf73 (diff)
downloadnova-ed1e6d792c5b37576640acd3e174c8a733c96b61.tar.gz
nova-ed1e6d792c5b37576640acd3e174c8a733c96b61.tar.xz
nova-ed1e6d792c5b37576640acd3e174c8a733c96b61.zip
Remove deprecated extension code.
The recent extensions refactoring (blueprint extension-refactor) deprecated ActionExtension and RequestExtension, replacing them with ControllerExtension. This patch completes the deprecation by removing those classes and all related support infrastructure, including ExtensionMiddleware and LazySerializationMiddleware. (The classes remain, as deprecated do-nothing stubs, for compatibility with existing api-paste.ini files.) Change-Id: I8272ac3cf432813d749db67b2e1ad1a72abbb784
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/common.py26
-rw-r--r--nova/api/openstack/compute/contrib/floating_ip_pools.py37
-rw-r--r--nova/api/openstack/compute/contrib/keypairs.py8
-rw-r--r--nova/api/openstack/compute/contrib/zones.py14
-rw-r--r--nova/api/openstack/compute/extensions.py25
-rw-r--r--nova/api/openstack/extensions.py274
-rw-r--r--nova/api/openstack/volume/__init__.py2
-rw-r--r--nova/api/openstack/volume/extensions.py24
-rw-r--r--nova/api/openstack/volume/snapshots.py74
-rw-r--r--nova/api/openstack/volume/types.py51
-rw-r--r--nova/api/openstack/volume/volumes.py133
-rw-r--r--nova/api/openstack/wsgi.py217
-rw-r--r--nova/api/openstack/xmlutil.py42
13 files changed, 151 insertions, 776 deletions
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index 0ac46d96e..2cc18661b 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -426,12 +426,6 @@ class MetadataXMLDeserializer(wsgi.XMLDeserializer):
return {'body': {'meta': metadata_item}}
-class MetadataHeadersSerializer(wsgi.ResponseHeadersSerializer):
-
- def delete(self, response, data):
- response.status_int = 204
-
-
metadata_nsmap = {None: xmlutil.XMLNS_V11}
@@ -459,26 +453,6 @@ class MetadataTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1, nsmap=metadata_nsmap)
-class MetadataXMLSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return MetadataTemplate()
-
- def create(self):
- return MetadataTemplate()
-
- def update_all(self):
- return MetadataTemplate()
-
- def show(self):
- return MetaItemTemplate()
-
- def update(self):
- return MetaItemTemplate()
-
- def default(self):
- return xmlutil.MasterTemplate(None, 1)
-
-
def check_snapshots_enabled(f):
@functools.wraps(f)
def inner(*args, **kwargs):
diff --git a/nova/api/openstack/compute/contrib/floating_ip_pools.py b/nova/api/openstack/compute/contrib/floating_ip_pools.py
index 01b9a3645..0bf2362af 100644
--- a/nova/api/openstack/compute/contrib/floating_ip_pools.py
+++ b/nova/api/openstack/compute/contrib/floating_ip_pools.py
@@ -37,20 +37,6 @@ def _translate_floating_ip_pools_view(pools):
}
-class FloatingIPPoolsController(object):
- """The Floating IP Pool API controller for the OpenStack API."""
-
- def __init__(self):
- self.network_api = network.API()
- super(FloatingIPPoolsController, self).__init__()
-
- def index(self, req):
- """Return a list of pools."""
- context = req.environ['nova.context']
- pools = self.network_api.get_floating_ip_pools(context)
- return _translate_floating_ip_pools_view(pools)
-
-
def make_float_ip(elem):
elem.set('name')
@@ -72,9 +58,19 @@ class FloatingIPPoolsTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1)
-class FloatingIPPoolsSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return FloatingIPPoolsTemplate()
+class FloatingIPPoolsController(object):
+ """The Floating IP Pool API controller for the OpenStack API."""
+
+ def __init__(self):
+ self.network_api = network.API()
+ super(FloatingIPPoolsController, self).__init__()
+
+ @wsgi.serializers(xml=FloatingIPPoolsTemplate)
+ def index(self, req):
+ """Return a list of pools."""
+ context = req.environ['nova.context']
+ pools = self.network_api.get_floating_ip_pools(context)
+ return _translate_floating_ip_pools_view(pools)
class Floating_ip_pools(extensions.ExtensionDescriptor):
@@ -89,15 +85,8 @@ class Floating_ip_pools(extensions.ExtensionDescriptor):
def get_resources(self):
resources = []
- body_serializers = {
- 'application/xml': FloatingIPPoolsSerializer(),
- }
-
- serializer = wsgi.ResponseSerializer(body_serializers)
-
res = extensions.ResourceExtension('os-floating-ip-pools',
FloatingIPPoolsController(),
- serializer=serializer,
member_actions={})
resources.append(res)
diff --git a/nova/api/openstack/compute/contrib/keypairs.py b/nova/api/openstack/compute/contrib/keypairs.py
index c09ca555f..504539d55 100644
--- a/nova/api/openstack/compute/contrib/keypairs.py
+++ b/nova/api/openstack/compute/contrib/keypairs.py
@@ -130,14 +130,6 @@ class KeypairController(object):
return {'keypairs': rval}
-class KeypairsSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return KeypairsTemplate()
-
- def default(self):
- return KeypairTemplate()
-
-
class Keypairs(extensions.ExtensionDescriptor):
"""Keypair Support"""
diff --git a/nova/api/openstack/compute/contrib/zones.py b/nova/api/openstack/compute/contrib/zones.py
index b68f3f4f5..539833ee2 100644
--- a/nova/api/openstack/compute/contrib/zones.py
+++ b/nova/api/openstack/compute/contrib/zones.py
@@ -195,20 +195,6 @@ class Controller(object):
return cooked
-class ZonesXMLSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return ZonesTemplate()
-
- def detail(self):
- return ZonesTemplate()
-
- def select(self):
- return WeightsTemplate()
-
- def default(self):
- return ZoneTemplate()
-
-
class Zones(extensions.ExtensionDescriptor):
"""Enables zones-related functionality such as adding child zones,
listing child zones, getting the capabilities of the local zone,
diff --git a/nova/api/openstack/compute/extensions.py b/nova/api/openstack/compute/extensions.py
index 39849e802..f5ebdfee9 100644
--- a/nova/api/openstack/compute/extensions.py
+++ b/nova/api/openstack/compute/extensions.py
@@ -25,21 +25,20 @@ FLAGS = flags.FLAGS
class ExtensionManager(base_extensions.ExtensionManager):
- def __new__(cls):
- if cls._ext_mgr is None:
- LOG.audit(_('Initializing extension manager.'))
+ def __init__(self):
+ LOG.audit(_('Initializing extension manager.'))
- cls._ext_mgr = super(ExtensionManager, cls).__new__(cls)
+ self.cls_list = FLAGS.osapi_compute_extension
+ self.extensions = {}
+ self._load_extensions()
- 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):
+ """Extensions middleware for WSGI.
+ Provided only for backwards compatibility with existing
+ api-paste.ini files. This middleware will be removed in future
+ versions of nova.
+ """
-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)
+ pass
diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py
index ce37e0a34..9a47a69d4 100644
--- a/nova/api/openstack/extensions.py
+++ b/nova/api/openstack/extensions.py
@@ -79,24 +79,6 @@ class ExtensionDescriptor(object):
resources = []
return resources
- def get_actions(self):
- """List of extensions.ActionExtension extension objects.
-
- Actions are verbs callable from the API.
-
- """
- actions = []
- return actions
-
- def get_request_extensions(self):
- """List of extensions.RequestExtension extension objects.
-
- Request extensions are used to handle custom request data.
-
- """
- request_exts = []
- return request_exts
-
def get_controller_extensions(self):
"""List of extensions.ControllerExtension extension objects.
@@ -124,92 +106,6 @@ class ExtensionDescriptor(object):
return '{%s}%s' % (cls.namespace, name)
-class ActionExtensionController(object):
- def __init__(self, application):
- self.application = application
- self.action_handlers = {}
-
- def add_action(self, action_name, handler):
- self.action_handlers[action_name] = handler
-
- def action(self, req, id, body):
- for action_name, handler in self.action_handlers.iteritems():
- if action_name in body:
- return handler(body, req, id)
- # no action handler found (bump to downstream application)
- res = self.application
- return res
-
-
-class ActionExtensionResource(wsgi.Resource):
-
- def __init__(self, application):
- controller = ActionExtensionController(application)
- wsgi.Resource.__init__(self, controller,
- serializer=wsgi.ResponseSerializer(),
- deserializer=wsgi.RequestDeserializer())
-
- def add_action(self, action_name, handler):
- self.controller.add_action(action_name, handler)
-
-
-class RequestExtensionController(object):
-
- def __init__(self, application):
- self.application = application
- self.handlers = []
- self.pre_handlers = []
-
- def add_handler(self, handler):
- self.handlers.append(handler)
-
- def add_pre_handler(self, pre_handler):
- self.pre_handlers.append(pre_handler)
-
- def process(self, req, *args, **kwargs):
- for pre_handler in self.pre_handlers:
- pre_handler(req)
-
- res = req.get_response(self.application)
- res.environ = req.environ
-
- # Don't call extensions if the main application returned an
- # unsuccessful status
- successful = 200 <= res.status_int < 400
- if not successful:
- return res
-
- # Deserialize the response body, if any
- body = None
- if res.body:
- body = utils.loads(res.body)
-
- # currently request handlers are un-ordered
- for handler in self.handlers:
- res = handler(req, res, body)
-
- # Reserialize the response body
- if body is not None:
- res.body = utils.dumps(body)
-
- return res
-
-
-class RequestExtensionResource(wsgi.Resource):
-
- def __init__(self, application):
- controller = RequestExtensionController(application)
- wsgi.Resource.__init__(self, controller,
- serializer=wsgi.ResponseSerializer(),
- deserializer=wsgi.RequestDeserializer())
-
- def add_handler(self, handler):
- self.controller.add_handler(handler)
-
- def add_pre_handler(self, pre_handler):
- self.controller.add_pre_handler(pre_handler)
-
-
def make_ext(elem):
elem.set('name')
elem.set('namespace')
@@ -281,106 +177,16 @@ class ExtensionsResource(wsgi.Resource):
raise webob.exc.HTTPNotFound()
+@utils.deprecated("The extension middleware is no longer necessary.")
class ExtensionMiddleware(base_wsgi.Middleware):
- """Extensions middleware for WSGI."""
- @classmethod
- def factory(cls, global_config, **local_config):
- """Paste factory."""
- def _factory(app):
- return cls(app, **local_config)
- return _factory
-
- def _action_ext_resources(self, application, ext_mgr, mapper):
- """Return a dict of ActionExtensionResource-s by collection."""
- action_resources = {}
- for action in ext_mgr.get_actions():
- if not action.collection in action_resources.keys():
- resource = ActionExtensionResource(application)
- mapper.connect("/:(project_id)/%s/:(id)/action.:(format)" %
- action.collection,
- action='action',
- controller=resource,
- conditions=dict(method=['POST']))
- mapper.connect("/:(project_id)/%s/:(id)/action" %
- action.collection,
- action='action',
- controller=resource,
- conditions=dict(method=['POST']))
- action_resources[action.collection] = resource
-
- return action_resources
-
- def _request_ext_resources(self, application, ext_mgr, mapper):
- """Returns a dict of RequestExtensionResource-s by collection."""
- request_ext_resources = {}
- for req_ext in ext_mgr.get_request_extensions():
- if not req_ext.key in request_ext_resources.keys():
- resource = RequestExtensionResource(application)
- mapper.connect(req_ext.url_route + '.:(format)',
- action='process',
- controller=resource,
- conditions=req_ext.conditions)
-
- mapper.connect(req_ext.url_route,
- action='process',
- controller=resource,
- conditions=req_ext.conditions)
- request_ext_resources[req_ext.key] = resource
-
- return request_ext_resources
-
- def __init__(self, application, ext_mgr=None):
-
- if ext_mgr is None:
- ext_mgr = ExtensionManager()
- self.ext_mgr = ext_mgr
-
- mapper = nova.api.openstack.ProjectMapper()
-
- # extended actions
- action_resources = self._action_ext_resources(application, ext_mgr,
- mapper)
- for action in ext_mgr.get_actions():
- LOG.debug(_('Extended action: %s'), action.action_name)
- resource = action_resources[action.collection]
- resource.add_action(action.action_name, action.handler)
-
- # extended requests
- req_controllers = self._request_ext_resources(application, ext_mgr,
- mapper)
- for request_ext in ext_mgr.get_request_extensions():
- LOG.debug(_('Extended request: %s'), request_ext.key)
- controller = req_controllers[request_ext.key]
- if request_ext.handler:
- controller.add_handler(request_ext.handler)
- if request_ext.pre_handler:
- controller.add_pre_handler(request_ext.pre_handler)
-
- self._router = routes.middleware.RoutesMiddleware(self._dispatch,
- mapper)
-
- super(ExtensionMiddleware, self).__init__(application)
-
- @webob.dec.wsgify(RequestClass=wsgi.Request)
- def __call__(self, req):
- """Route the incoming request with router."""
- req.environ['extended.app'] = self.application
- return self._router
-
- @staticmethod
- @webob.dec.wsgify(RequestClass=wsgi.Request)
- def _dispatch(req):
- """Dispatch the request.
-
- Returns the routed WSGI app's response or defers to the extended
- application.
+ """Extensions middleware for WSGI.
- """
- match = req.environ['wsgiorg.routing_args'][1]
- if not match:
- return req.environ['extended.app']
- app = match['controller']
- return app
+ Provided only for backwards compatibility with existing
+ api-paste.ini files. This middleware will be removed in future
+ versions of nova.
+ """
+
+ pass
class ExtensionManager(object):
@@ -391,12 +197,6 @@ class ExtensionManager(object):
"""
- _ext_mgr = None
-
- @classmethod
- def reset(cls):
- cls._ext_mgr = None
-
def register(self, ext):
# Do nothing if the extension doesn't check out
if not self._check_extension(ext):
@@ -425,30 +225,6 @@ class ExtensionManager(object):
pass
return resources
- def get_actions(self):
- """Returns a list of ActionExtension objects."""
- actions = []
- for ext in self.extensions.values():
- try:
- actions.extend(ext.get_actions())
- except AttributeError:
- # NOTE(dprince): Extension aren't required to have action
- # extensions
- pass
- return actions
-
- def get_request_extensions(self):
- """Returns a list of RequestExtension objects."""
- request_exts = []
- for ext in self.extensions.values():
- try:
- request_exts.extend(ext.get_request_extensions())
- except AttributeError:
- # NOTE(dprince): Extension aren't required to have request
- # extensions
- pass
- return request_exts
-
def get_controller_extensions(self):
"""Returns a list of ControllerExtension objects."""
controller_exts = []
@@ -525,32 +301,6 @@ class ControllerExtension(object):
self.controller = controller
-@utils.deprecated("Superseded by ControllerExtension")
-class RequestExtension(object):
- """Extend requests and responses of core nova OpenStack API resources.
-
- Provide a way to add data to responses and handle custom request data
- that is sent to core nova OpenStack API controllers.
-
- """
- def __init__(self, method, url_route, handler=None, pre_handler=None):
- self.url_route = url_route
- self.handler = handler
- self.conditions = dict(method=[method])
- self.key = "%s-%s" % (method, url_route)
- self.pre_handler = pre_handler
-
-
-@utils.deprecated("Superseded by ControllerExtension")
-class ActionExtension(object):
- """Add custom actions to core nova OpenStack API resources."""
-
- def __init__(self, collection, action_name, handler):
- self.collection = collection
- self.action_name = action_name
- self.handler = handler
-
-
class ResourceExtension(object):
"""Add top level resources to the OpenStack API in nova."""
@@ -570,14 +320,6 @@ class ResourceExtension(object):
self.serializer = serializer
-class ExtensionsXMLSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return ExtensionsTemplate()
-
- def show(self):
- return ExtensionTemplate()
-
-
def wrap_errors(fn):
"""Ensure errors are not passed along."""
def wrapped(*args, **kwargs):
diff --git a/nova/api/openstack/volume/__init__.py b/nova/api/openstack/volume/__init__.py
index 9e8a5d789..f8d0f28bd 100644
--- a/nova/api/openstack/volume/__init__.py
+++ b/nova/api/openstack/volume/__init__.py
@@ -62,8 +62,6 @@ class APIRouter(base_wsgi.Router):
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)
diff --git a/nova/api/openstack/volume/extensions.py b/nova/api/openstack/volume/extensions.py
index d1007629e..eccac660e 100644
--- a/nova/api/openstack/volume/extensions.py
+++ b/nova/api/openstack/volume/extensions.py
@@ -25,20 +25,20 @@ FLAGS = flags.FLAGS
class ExtensionManager(base_extensions.ExtensionManager):
- def __new__(cls):
- if cls._ext_mgr is None:
- LOG.audit(_('Initializing extension manager.'))
+ def __init__(self):
+ LOG.audit(_('Initializing extension manager.'))
- cls._ext_mgr = super(ExtensionManager, cls).__new__(cls)
+ self.cls_list = FLAGS.osapi_volume_extension
+ self.extensions = {}
+ self._load_extensions()
- 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):
+ """Extensions middleware for WSGI.
+ Provided only for backwards compatibility with existing
+ api-paste.ini files. This middleware will be removed in future
+ versions of nova.
+ """
-class ExtensionMiddleware(base_extensions.ExtensionMiddleware):
- def __init__(self, application, ext_mgr=None):
- ext_mgr = ExtensionManager()
- super(ExtensionMiddleware, self).__init__(application, ext_mgr)
+ pass
diff --git a/nova/api/openstack/volume/snapshots.py b/nova/api/openstack/volume/snapshots.py
index ec12c052b..36687d736 100644
--- a/nova/api/openstack/volume/snapshots.py
+++ b/nova/api/openstack/volume/snapshots.py
@@ -57,6 +57,32 @@ def _translate_snapshot_summary_view(context, vol):
return d
+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 SnapshotsController(object):
"""The Volumes API controller for the OpenStack API."""
@@ -64,6 +90,7 @@ class SnapshotsController(object):
self.volume_api = volume.API()
super(SnapshotsController, self).__init__()
+ @wsgi.serializers(xml=SnapshotTemplate)
def show(self, req, id):
"""Return data about the given snapshot."""
context = req.environ['nova.context']
@@ -88,10 +115,12 @@ class SnapshotsController(object):
return exc.HTTPNotFound()
return webob.Response(status_int=202)
+ @wsgi.serializers(xml=SnapshotsTemplate)
def index(self, req):
"""Returns a summary list of snapshots."""
return self._items(req, entity_maker=_translate_snapshot_summary_view)
+ @wsgi.serializers(xml=SnapshotsTemplate)
def detail(self, req):
"""Returns a detailed list of snapshots."""
return self._items(req, entity_maker=_translate_snapshot_detail_view)
@@ -105,6 +134,7 @@ class SnapshotsController(object):
res = [entity_maker(context, snapshot) for snapshot in limited_list]
return {'snapshots': res}
+ @wsgi.serializers(xml=SnapshotTemplate)
def create(self, req, body):
"""Creates a new snapshot."""
context = req.environ['nova.context']
@@ -135,47 +165,5 @@ class SnapshotsController(object):
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)
+ return wsgi.Resource(SnapshotsController())
diff --git a/nova/api/openstack/volume/types.py b/nova/api/openstack/volume/types.py
index d324914a4..609a6cfc9 100644
--- a/nova/api/openstack/volume/types.py
+++ b/nova/api/openstack/volume/types.py
@@ -25,26 +25,6 @@ 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')
@@ -68,20 +48,27 @@ class VolumeTypesTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(root, 1)
-class VolumeTypesSerializer(xmlutil.XMLTemplateSerializer):
- def index(self):
- return VolumeTypesTemplate()
+class VolumeTypesController(object):
+ """ The volume types API controller for the Openstack API """
- def default(self):
- return VolumeTypeTemplate()
+ @wsgi.serializers(xml=VolumeTypesTemplate)
+ def index(self, req):
+ """ Returns the list of volume types """
+ context = req.environ['nova.context']
+ return volume_types.get_all_types(context)
+
+ @wsgi.serializers(xml=VolumeTypeTemplate)
+ 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()
-def create_resource():
- body_serializers = {
- 'application/xml': VolumeTypesSerializer(),
- }
- serializer = wsgi.ResponseSerializer(body_serializers)
+ return {'volume_type': vol_type}
- deserializer = wsgi.RequestDeserializer()
- return wsgi.Resource(VolumeTypesController(), serializer=serializer)
+def create_resource():
+ return wsgi.Resource(VolumeTypesController())
diff --git a/nova/api/openstack/volume/volumes.py b/nova/api/openstack/volume/volumes.py
index b37a56374..397358ca1 100644
--- a/nova/api/openstack/volume/volumes.py
+++ b/nova/api/openstack/volume/volumes.py
@@ -109,6 +109,48 @@ def _translate_volume_summary_view(context, vol):
return d
+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 VolumeController(object):
"""The Volumes API controller for the OpenStack API."""
@@ -116,6 +158,7 @@ class VolumeController(object):
self.volume_api = volume.API()
super(VolumeController, self).__init__()
+ @wsgi.serializers(xml=VolumeTemplate)
def show(self, req, id):
"""Return data about the given volume."""
context = req.environ['nova.context']
@@ -140,10 +183,12 @@ class VolumeController(object):
raise exc.HTTPNotFound()
return webob.Response(status_int=202)
+ @wsgi.serializers(xml=VolumesTemplate)
def index(self, req):
"""Returns a summary list of volumes."""
return self._items(req, entity_maker=_translate_volume_summary_view)
+ @wsgi.serializers(xml=VolumesTemplate)
def detail(self, req):
"""Returns a detailed list of volumes."""
return self._items(req, entity_maker=_translate_volume_detail_view)
@@ -157,6 +202,7 @@ class VolumeController(object):
res = [entity_maker(context, vol) for vol in limited_list]
return {'volumes': res}
+ @wsgi.serializers(xml=VolumeTemplate)
def create(self, req, body):
"""Creates a new volume."""
context = req.environ['nova.context']
@@ -201,90 +247,5 @@ class VolumeController(object):
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)
+ return wsgi.Resource(VolumeController())
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index 3bf1bef00..d5a3d95b3 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -216,104 +216,6 @@ class MetadataXMLDeserializer(XMLDeserializer):
return metadata
-class RequestHeadersDeserializer(ActionDispatcher):
- """Default request headers deserializer"""
-
- def deserialize(self, request, action):
- return self.dispatch(request, action=action)
-
- def default(self, request):
- return {}
-
-
-class RequestDeserializer(object):
- """Break up a Request object into more useful pieces."""
-
- def __init__(self, body_deserializers=None, headers_deserializer=None):
- self.body_deserializers = {
- 'application/xml': XMLDeserializer(),
- 'application/json': JSONDeserializer(),
- }
- self.body_deserializers.update(body_deserializers or {})
-
- self.headers_deserializer = headers_deserializer or \
- RequestHeadersDeserializer()
-
- def deserialize(self, request):
- """Extract necessary pieces of the request.
-
- :param request: Request object
- :returns tuple of expected controller action name, dictionary of
- keyword arguments to pass to the controller, the expected
- content type of the response
-
- """
- action_args = self.get_action_args(request.environ)
- action = action_args.pop('action', None)
-
- action_args.update(self.deserialize_headers(request, action))
- action_args.update(self.deserialize_body(request, action))
-
- accept = self.get_expected_content_type(request)
-
- return (action, action_args, accept)
-
- def deserialize_headers(self, request, action):
- return self.headers_deserializer.deserialize(request, action)
-
- def deserialize_body(self, request, action):
- try:
- content_type = request.get_content_type()
- except exception.InvalidContentType:
- LOG.debug(_("Unrecognized Content-Type provided in request"))
- return {}
-
- if content_type is None:
- LOG.debug(_("No Content-Type provided in request"))
- return {}
-
- if not len(request.body) > 0:
- LOG.debug(_("Empty body provided in request"))
- return {}
-
- try:
- deserializer = self.get_body_deserializer(content_type)
- except exception.InvalidContentType:
- LOG.debug(_("Unable to deserialize body as provided Content-Type"))
- raise
-
- return deserializer.deserialize(request.body, action)
-
- def get_body_deserializer(self, content_type):
- try:
- ctype = _CONTENT_TYPE_MAP.get(content_type, content_type)
- return self.body_deserializers[ctype]
- except (KeyError, TypeError):
- raise exception.InvalidContentType(content_type=content_type)
-
- def get_expected_content_type(self, request):
- return request.best_match_content_type()
-
- def get_action_args(self, request_environment):
- """Parse dictionary created by routes library."""
- try:
- args = request_environment['wsgiorg.routing_args'][1].copy()
- except Exception:
- return {}
-
- try:
- del args['controller']
- except KeyError:
- pass
-
- try:
- del args['format']
- except KeyError:
- pass
-
- return args
-
-
class DictSerializer(ActionDispatcher):
"""Default request body serialization"""
@@ -435,104 +337,16 @@ class XMLDictSerializer(DictSerializer):
return etree.tostring(root, encoding='UTF-8', xml_declaration=True)
-class ResponseHeadersSerializer(ActionDispatcher):
- """Default response headers serialization"""
-
- def serialize(self, response, data, action):
- self.dispatch(response, data, action=action)
- context = response.request.environ.get('nova.context')
- if context:
- response.headers['X-Compute-Request-Id'] = context.request_id
-
- def default(self, response, data):
- response.status_int = 200
-
-
-class ResponseSerializer(object):
- """Encode the necessary pieces into a response object"""
-
- def __init__(self, body_serializers=None, headers_serializer=None):
- self.body_serializers = {
- 'application/xml': XMLDictSerializer(),
- 'application/json': JSONDictSerializer(),
- }
- self.body_serializers.update(body_serializers or {})
-
- self.headers_serializer = headers_serializer or \
- ResponseHeadersSerializer()
-
- def serialize(self, request, response_data, content_type,
- action='default'):
- """Serialize a dict into a string and wrap in a wsgi.Request object.
-
- :param response_data: dict produced by the Controller
- :param content_type: expected mimetype of serialized response body
-
- """
- response = webob.Response(request=request)
- self.serialize_headers(response, response_data, action)
- self.serialize_body(request, response, response_data, content_type,
- action)
- return response
-
- def serialize_headers(self, response, data, action):
- self.headers_serializer.serialize(response, data, action)
-
- def serialize_body(self, request, response, data, content_type, action):
- response.headers['Content-Type'] = content_type
- if data is not None:
- serializer = self.get_body_serializer(content_type)
- lazy_serialize = request.environ.get('nova.lazy_serialize', False)
- if lazy_serialize:
- response.body = utils.dumps(data)
- request.environ['nova.serializer'] = serializer
- request.environ['nova.action'] = action
- if (hasattr(serializer, 'get_template') and
- 'nova.template' not in request.environ):
-
- template = serializer.get_template(action)
- request.environ['nova.template'] = template
- else:
- response.body = serializer.serialize(data, action)
-
- def get_body_serializer(self, content_type):
- try:
- ctype = _CONTENT_TYPE_MAP.get(content_type, content_type)
- return self.body_serializers[ctype]
- except (KeyError, TypeError):
- raise exception.InvalidContentType(content_type=content_type)
+@utils.deprecated("The lazy serialization middleware is no longer necessary.")
+class LazySerializationMiddleware(wsgi.Middleware):
+ """Lazy serialization middleware.
+ Provided only for backwards compatibility with existing
+ api-paste.ini files. This middleware will be removed in future
+ versions of nova.
+ """
-class LazySerializationMiddleware(wsgi.Middleware):
- """Lazy serialization middleware."""
- @webob.dec.wsgify(RequestClass=Request)
- def __call__(self, req):
- # Request lazy serialization
- req.environ['nova.lazy_serialize'] = True
-
- response = req.get_response(self.application)
-
- # See if we're using the simple serialization driver
- simple_serial = req.environ.get('nova.simple_serial')
- if simple_serial is not None:
- body_obj = utils.loads(response.body)
- response.body = simple_serial.serialize(body_obj)
- return response
-
- # See if there's a serializer...
- serializer = req.environ.get('nova.serializer')
- if serializer is None:
- return response
-
- # OK, build up the arguments for the serialize() method
- kwargs = dict(action=req.environ['nova.action'])
- if 'nova.template' in req.environ:
- kwargs['template'] = req.environ['nova.template']
-
- # Re-serialize the body
- response.body = serializer.serialize(utils.loads(response.body),
- **kwargs)
- return response
+ pass
def serializers(**serializers):
@@ -698,20 +512,7 @@ class ResponseObject(object):
response.headers[hdr] = value
response.headers['Content-Type'] = content_type
if self.obj is not None:
- # TODO(Vek): When lazy serialization is retired, so can
- # this inner 'if'...
- lazy_serialize = request.environ.get('nova.lazy_serialize', False)
- if lazy_serialize:
- response.body = utils.dumps(self.obj)
- request.environ['nova.simple_serial'] = serializer
- # NOTE(Vek): Temporary ugly hack to support xml
- # templates in extensions, until we can
- # fold extensions into Resource and do away
- # with lazy serialization...
- if _MEDIA_TYPE_MAP.get(content_type) == 'xml':
- request.environ['nova.template'] = serializer
- else:
- response.body = serializer.serialize(self.obj)
+ response.body = serializer.serialize(self.obj)
return response
diff --git a/nova/api/openstack/xmlutil.py b/nova/api/openstack/xmlutil.py
index 4b64d4a8f..2485ef2c5 100644
--- a/nova/api/openstack/xmlutil.py
+++ b/nova/api/openstack/xmlutil.py
@@ -858,48 +858,6 @@ class TemplateBuilder(object):
raise NotImplementedError(_("subclasses must implement construct()!"))
-class XMLTemplateSerializer(wsgi.ActionDispatcher):
- """Template-based XML serializer.
-
- Data serializer that uses templates to perform its serialization.
- """
-
- def get_template(self, action='default'):
- """Retrieve the template to use for serialization."""
-
- return self.dispatch(action=action)
-
- def serialize(self, data, action='default', template=None):
- """Serialize data.
-
- :param data: The data to serialize.
- :param action: The action, for identifying the template to
- use. If no template is provided,
- get_template() will be called with this action
- to retrieve the template.
- :param template: The template to use in serialization.
- """
-
- # No template provided, look one up
- if template is None:
- template = self.get_template(action)
-
- # Still couldn't find a template; try the base
- # XMLDictSerializer
- if template is None:
- serial = wsgi.XMLDictSerializer()
- return serial.serialize(data, action=action)
-
- # Serialize the template
- return template.serialize(data, encoding='UTF-8',
- xml_declaration=True)
-
- def default(self):
- """Retrieve the default template to use."""
-
- return None
-
-
def make_links(parent, selector=None):
"""
Attach an Atom <links> element to the parent.