summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
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.