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
This commit is contained in:
Kevin L. Mitchell
2012-01-19 16:20:04 -06:00
parent 4f204a6d75
commit ed1e6d792c
30 changed files with 275 additions and 1318 deletions

View File

@@ -90,12 +90,12 @@ use = call:nova.api.openstack.urlmap:urlmap_factory
/v1: openstack_volume_api_v1
[pipeline:openstack_compute_api_v2]
pipeline = faultwrap noauth ratelimit serialize compute_extensions osapi_compute_app_v2
pipeline = faultwrap noauth ratelimit osapi_compute_app_v2
# NOTE(vish): use the following pipeline for deprecated auth
# pipeline = faultwrap auth ratelimit serialize extensions osapi_compute_app_v2
# pipeline = faultwrap auth ratelimit osapi_compute_app_v2
[pipeline:openstack_volume_api_v1]
pipeline = faultwrap noauth ratelimit serialize volume_extensions osapi_volume_app_v1
pipeline = faultwrap noauth ratelimit osapi_volume_app_v1
[filter:faultwrap]
paste.filter_factory = nova.api.openstack:FaultWrapper.factory
@@ -109,15 +109,6 @@ paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory
[filter:ratelimit]
paste.filter_factory = nova.api.openstack.compute.limits:RateLimitingMiddleware.factory
[filter:serialize]
paste.filter_factory = nova.api.openstack.wsgi:LazySerializationMiddleware.factory
[filter:compute_extensions]
paste.filter_factory = nova.api.openstack.compute.extensions:ExtensionMiddleware.factory
[filter:volume_extensions]
paste.filter_factory = nova.api.openstack.volume.extensions:ExtensionMiddleware.factory
[app:osapi_compute_app_v2]
paste.app_factory = nova.api.openstack.compute:APIRouter.factory

View File

@@ -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):

View File

@@ -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)

View File

@@ -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"""

View File

@@ -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,

View File

@@ -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)
cls.cls_list = FLAGS.osapi_compute_extension
cls._ext_mgr.extensions = {}
cls._ext_mgr._load_extensions()
return cls._ext_mgr
self.cls_list = FLAGS.osapi_compute_extension
self.extensions = {}
self._load_extensions()
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)
"""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.
"""
pass

View File

@@ -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
"""Extensions middleware for WSGI.
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
Provided only for backwards compatibility with existing
api-paste.ini files. This middleware will be removed in future
versions of nova.
"""
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.
"""
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return req.environ['extended.app']
app = match['controller']
return app
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):

View File

@@ -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)

View File

@@ -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)
cls.cls_list = FLAGS.osapi_volume_extension
cls._ext_mgr.extensions = {}
cls._ext_mgr._load_extensions()
return cls._ext_mgr
self.cls_list = FLAGS.osapi_volume_extension
self.extensions = {}
self._load_extensions()
class ExtensionMiddleware(base_extensions.ExtensionMiddleware):
def __init__(self, application, ext_mgr=None):
ext_mgr = ExtensionManager()
super(ExtensionMiddleware, self).__init__(application, ext_mgr)
"""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.
"""
pass

View File

@@ -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())

View File

@@ -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()
return {'volume_type': vol_type}
def create_resource():
body_serializers = {
'application/xml': VolumeTypesSerializer(),
}
serializer = wsgi.ResponseSerializer(body_serializers)
deserializer = wsgi.RequestDeserializer()
return wsgi.Resource(VolumeTypesController(), serializer=serializer)
return wsgi.Resource(VolumeTypesController())

View File

@@ -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())

View File

@@ -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."""
@webob.dec.wsgify(RequestClass=Request)
def __call__(self, req):
# Request lazy serialization
req.environ['nova.lazy_serialize'] = True
"""Lazy serialization middleware.
response = req.get_response(self.application)
Provided only for backwards compatibility with existing
api-paste.ini files. This middleware will be removed in future
versions of nova.
"""
# 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

View File

@@ -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.

View File

@@ -123,9 +123,7 @@ class CreateBackupTests(test.TestCase):
self.backup_stubs = fakes.stub_out_compute_api_backup(self.stubs)
self.flags(allow_admin_api=True)
router = compute_api.APIRouter()
ext_middleware = extensions.ExtensionMiddleware(router)
self.app = wsgi.LazySerializationMiddleware(ext_middleware)
self.app = compute_api.APIRouter()
self.uuid = utils.gen_uuid()

View File

@@ -120,10 +120,7 @@ class DiskConfigTestCase(test.TestCase):
self.stubs.Set(nova.db, 'instance_create', fake_instance_create)
app = compute.APIRouter()
app = extensions.ExtensionMiddleware(app)
app = wsgi.LazySerializationMiddleware(app)
self.app = app
self.app = compute.APIRouter()
def assertDiskConfig(self, dict_, value):
self.assert_(API_DISK_CONFIG in dict_)

View File

@@ -56,12 +56,12 @@ class FloatingIpPoolTest(test.TestCase):
class FloatingIpPoolSerializerTest(test.TestCase):
def test_index_serializer(self):
serializer = floating_ip_pools.FloatingIPPoolsSerializer()
serializer = floating_ip_pools.FloatingIPPoolsTemplate()
text = serializer.serialize(dict(
floating_ip_pools=[
dict(name='nova'),
dict(name='other')
]), 'index')
]))
tree = etree.fromstring(text)

View File

@@ -54,13 +54,11 @@ class ServerActionsTest(test.TestCase):
self.compute_api = nova.compute.API()
self.router = compute.APIRouter()
ext_middleware = extensions.ExtensionMiddleware(self.router)
self.app = wsgi.LazySerializationMiddleware(ext_middleware)
def test_get_actions(self):
uuid = nova.utils.gen_uuid()
req = fakes.HTTPRequest.blank('/fake/servers/%s/actions' % uuid)
res = req.get_response(self.app)
res = req.get_response(self.router)
output = json.loads(res.body)
expected = {'actions': [
{'action': 'rebuild', 'error': None, 'created_at': str(dt)},

View File

@@ -48,13 +48,11 @@ class ServerDiagnosticsTest(test.TestCase):
self.compute_api = nova.compute.API()
self.router = compute.APIRouter()
ext_middleware = extensions.ExtensionMiddleware(self.router)
self.app = wsgi.LazySerializationMiddleware(ext_middleware)
def test_get_diagnostics(self):
uuid = nova.utils.gen_uuid()
req = fakes.HTTPRequest.blank('/fake/servers/%s/diagnostics' % uuid)
res = req.get_response(self.app)
res = req.get_response(self.router)
output = json.loads(res.body)
self.assertEqual(output, {'data': 'Some diagnostic info'})

View File

@@ -18,6 +18,7 @@
import webob.exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
class FoxInSocksController(object):
@@ -26,6 +27,39 @@ class FoxInSocksController(object):
return "Try to say this Mr. Knox, sir..."
class FoxInSocksServerControllerExtension(wsgi.Controller):
@wsgi.action('add_tweedle')
def _add_tweedle(self, req, id, body):
return "Tweedle Beetle Added."
@wsgi.action('delete_tweedle')
def _delete_tweedle(self, req, id, body):
return "Tweedle Beetle Deleted."
@wsgi.action('fail')
def _fail(self, req, id, body):
raise webob.exc.HTTPBadRequest(explanation='Tweedle fail')
class FoxInSocksFlavorGooseControllerExtension(wsgi.Controller):
@wsgi.extends
def show(self, req, resp_obj, id):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
resp_obj.obj['flavor']['googoose'] = req.GET.get('chewing')
class FoxInSocksFlavorBandsControllerExtension(wsgi.Controller):
@wsgi.extends
def show(self, req, resp_obj, id):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
resp_obj.obj['big_bands'] = 'Pig Bands!'
class Foxinsocks(extensions.ExtensionDescriptor):
"""The Fox In Socks Extension"""
@@ -44,50 +78,17 @@ class Foxinsocks(extensions.ExtensionDescriptor):
resources.append(resource)
return resources
def get_actions(self):
actions = []
actions.append(extensions.ActionExtension('servers', 'add_tweedle',
self._add_tweedle))
actions.append(extensions.ActionExtension('servers', 'delete_tweedle',
self._delete_tweedle))
actions.append(extensions.ActionExtension('servers', 'fail',
self._fail))
return actions
def get_controller_extensions(self):
extension_list = []
def get_request_extensions(self):
request_exts = []
extension_set = [
(FoxInSocksServerControllerExtension, 'servers'),
(FoxInSocksFlavorGooseControllerExtension, 'flavors'),
(FoxInSocksFlavorBandsControllerExtension, 'flavors'),
]
for klass, collection in extension_set:
controller = klass()
ext = extensions.ControllerExtension(self, collection, controller)
extension_list.append(ext)
def _goose_handler(req, res, body):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
body['flavor']['googoose'] = req.GET.get('chewing')
return res
req_ext1 = extensions.RequestExtension('GET',
'/v2/:(project_id)/flavors/:(id)',
_goose_handler)
request_exts.append(req_ext1)
def _bands_handler(req, res, body):
#NOTE: This only handles JSON responses.
# You can use content type header to test for XML.
body['big_bands'] = 'Pig Bands!'
return res
req_ext2 = extensions.RequestExtension('GET',
'/v2/:(project_id)/flavors/:(id)',
_bands_handler)
request_exts.append(req_ext2)
return request_exts
def _add_tweedle(self, input_dict, req, id):
return "Tweedle Beetle Added."
def _delete_tweedle(self, input_dict, req, id):
return "Tweedle Beetle Deleted."
def _fail(self, input_dict, req, id):
raise webob.exc.HTTPBadRequest(explanation='Tweedle fail')
return extension_list

View File

@@ -144,7 +144,6 @@ class ExtensionTestCase(test.TestCase):
if fox not in ext_list:
ext_list.append(fox)
self.flags(osapi_compute_extension=ext_list)
compute_extensions.ExtensionManager.reset()
class ExtensionControllerTest(ExtensionTestCase):
@@ -189,10 +188,8 @@ class ExtensionControllerTest(ExtensionTestCase):
def test_list_extensions_json(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/extensions")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
# Make sure we have all the extensions.
@@ -218,10 +215,8 @@ class ExtensionControllerTest(ExtensionTestCase):
def test_get_extension_json(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/extensions/FOXNSOX")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
data = json.loads(response.body)
@@ -235,18 +230,15 @@ class ExtensionControllerTest(ExtensionTestCase):
def test_get_non_existing_extension_json(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
request = webob.Request.blank("/fake/extensions/4")
response = request.get_response(ext_midware)
response = request.get_response(app)
self.assertEqual(404, response.status_int)
def test_list_extensions_xml(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/extensions")
request.accept = "application/xml"
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
print response.body
@@ -270,11 +262,9 @@ class ExtensionControllerTest(ExtensionTestCase):
def test_get_extension_xml(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/extensions/FOXNSOX")
request.accept = "application/xml"
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
xml = response.body
print xml
@@ -297,10 +287,8 @@ class ResourceExtensionTest(ExtensionTestCase):
def test_no_extension_present(self):
manager = StubExtensionManager(None)
app = compute.APIRouter(manager)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/blah")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(404, response.status_int)
def test_get_resources(self):
@@ -308,10 +296,8 @@ class ResourceExtensionTest(ExtensionTestCase):
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = compute.APIRouter(manager)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/tweedles")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
self.assertEqual(response_body, response.body)
@@ -320,10 +306,8 @@ class ResourceExtensionTest(ExtensionTestCase):
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = compute.APIRouter(manager)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/tweedles")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
self.assertEqual(response_body, response.body)
@@ -332,11 +316,9 @@ class ResourceExtensionTest(ExtensionTestCase):
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = compute.APIRouter(manager)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/tweedles")
request.method = "POST"
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(400, response.status_int)
self.assertEqual('application/json', response.content_type)
body = json.loads(response.body)
@@ -353,10 +335,8 @@ class ResourceExtensionTest(ExtensionTestCase):
StubController(response_body))
manager = StubExtensionManager(res_ext)
app = compute.APIRouter(manager)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/tweedles/1")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(404, response.status_int)
self.assertEqual('application/json', response.content_type)
body = json.loads(response.body)
@@ -393,10 +373,8 @@ class ExtensionManagerTest(ExtensionTestCase):
def test_get_resources(self):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank("/fake/foxnsocks")
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
self.assertEqual(response_body, response.body)
@@ -404,8 +382,7 @@ class ExtensionManagerTest(ExtensionTestCase):
# Don't need the serialization middleware here because we're
# not testing any serialization
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ext_mgr = ext_midware.ext_mgr
ext_mgr = compute_extensions.ExtensionManager()
ext_mgr.register(InvalidExtension())
self.assertTrue('FOXNSOX' in ext_mgr.extensions)
self.assertTrue('THIRD' not in ext_mgr.extensions)
@@ -413,8 +390,7 @@ class ExtensionManagerTest(ExtensionTestCase):
def test_admin_extensions(self):
self.flags(allow_admin_api=True)
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ext_mgr = ext_midware.ext_mgr
ext_mgr = compute_extensions.ExtensionManager()
ext_mgr.register(AdminExtension())
self.assertTrue('FOXNSOX' in ext_mgr.extensions)
self.assertTrue('ADMIN' in ext_mgr.extensions)
@@ -422,8 +398,7 @@ class ExtensionManagerTest(ExtensionTestCase):
def test_admin_extensions_no_admin_api(self):
self.flags(allow_admin_api=False)
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ext_mgr = ext_midware.ext_mgr
ext_mgr = compute_extensions.ExtensionManager()
ext_mgr.register(AdminExtension())
self.assertTrue('FOXNSOX' in ext_mgr.extensions)
self.assertTrue('ADMIN' not in ext_mgr.extensions)
@@ -433,13 +408,11 @@ class ActionExtensionTest(ExtensionTestCase):
def _send_server_action_request(self, url, body):
app = compute.APIRouter()
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
request = webob.Request.blank(url)
request.method = 'POST'
request.content_type = 'application/json'
request.body = json.dumps(body)
response = request.get_response(ser_midware)
response = request.get_response(app)
return response
def test_extended_action(self):
@@ -494,35 +467,30 @@ class ActionExtensionTest(ExtensionTestCase):
class RequestExtensionTest(ExtensionTestCase):
def test_get_resources_with_stub_mgr(self):
class GooGoose(wsgi.Controller):
@wsgi.extends
def show(self, req, resp_obj, id):
# only handle JSON responses
resp_obj.obj['flavor']['googoose'] = req.GET.get('chewing')
def _req_handler(req, res, body):
# only handle JSON responses
body['flavor']['googoose'] = req.GET.get('chewing')
return res
req_ext = base_extensions.ControllerExtension(
StubControllerExtension(), 'flavors', GooGoose())
req_ext = base_extensions.RequestExtension('GET',
'/v2/fake/flavors/:(id)',
_req_handler)
manager = StubExtensionManager(None, None, req_ext)
app = fakes.wsgi_app(serialization=base_wsgi.Middleware)
ext_midware = compute_extensions.ExtensionMiddleware(app, manager)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
manager = StubExtensionManager(None, None, None, req_ext)
app = fakes.wsgi_app(ext_mgr=manager)
request = webob.Request.blank("/v2/fake/flavors/1?chewing=bluegoo")
request.environ['api.version'] = '2'
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
response_data = json.loads(response.body)
self.assertEqual('bluegoo', response_data['flavor']['googoose'])
def test_get_resources_with_mgr(self):
app = fakes.wsgi_app(serialization=base_wsgi.Middleware)
ext_midware = compute_extensions.ExtensionMiddleware(app)
ser_midware = wsgi.LazySerializationMiddleware(ext_midware)
app = fakes.wsgi_app()
request = webob.Request.blank("/v2/fake/flavors/1?chewing=newblue")
request.environ['api.version'] = '2'
response = request.get_response(ser_midware)
response = request.get_response(app)
self.assertEqual(200, response.status_int)
response_data = json.loads(response.body)
print response_data
@@ -611,7 +579,7 @@ class ControllerExtensionTest(ExtensionTestCase):
class ExtensionsXMLSerializerTest(test.TestCase):
def test_serialize_extension(self):
serializer = base_extensions.ExtensionsXMLSerializer()
serializer = base_extensions.ExtensionTemplate()
data = {'extension': {
'name': 'ext1',
'namespace': 'http://docs.rack.com/servers/api/ext/pie/v1.0',
@@ -625,7 +593,7 @@ class ExtensionsXMLSerializerTest(test.TestCase):
'type': 'application/vnd.sun.wadl+xml',
'href': 'http://docs.rack.com/servers/api/ext/cs.wadl'}]}}
xml = serializer.serialize(data, 'show')
xml = serializer.serialize(data)
print xml
root = etree.XML(xml)
ext_dict = data['extension']
@@ -644,7 +612,7 @@ class ExtensionsXMLSerializerTest(test.TestCase):
xmlutil.validate_schema(root, 'extension')
def test_serialize_extensions(self):
serializer = base_extensions.ExtensionsXMLSerializer()
serializer = base_extensions.ExtensionsTemplate()
data = {"extensions": [{
"name": "Public Image Extension",
"namespace": "http://foo.com/api/ext/pie/v1.0",
@@ -670,7 +638,7 @@ class ExtensionsXMLSerializerTest(test.TestCase):
"type": "application/vnd.sun.wadl+xml",
"href": "http://foo.com/api/ext/cs-cbs.wadl"}]}]}
xml = serializer.serialize(data, 'index')
xml = serializer.serialize(data)
print xml
root = etree.XML(xml)
ext_elems = root.findall('{0}extension'.format(NS))

View File

@@ -81,8 +81,7 @@ class LimitsControllerTest(BaseLimitTestSuite):
def setUp(self):
"""Run before each test."""
BaseLimitTestSuite.setUp(self)
self.controller = wsgi.LazySerializationMiddleware(
limits.create_resource())
self.controller = limits.create_resource()
self.maxDiff = None
def _get_index_request(self, accept_header="application/json"):

View File

@@ -50,7 +50,7 @@ class Context(object):
class FakeRouter(wsgi.Router):
def __init__(self):
def __init__(self, ext_mgr=None):
pass
@webob.dec.wsgify
@@ -74,10 +74,9 @@ def fake_wsgi(self, req):
def wsgi_app(inner_app_v2=None, fake_auth=True, fake_auth_context=None,
serialization=os_wsgi.LazySerializationMiddleware,
use_no_auth=False):
use_no_auth=False, ext_mgr=None):
if not inner_app_v2:
inner_app_v2 = compute.APIRouter()
inner_app_v2 = compute.APIRouter(ext_mgr)
if fake_auth:
if fake_auth_context is not None:
@@ -85,19 +84,13 @@ def wsgi_app(inner_app_v2=None, fake_auth=True, fake_auth_context=None,
else:
ctxt = context.RequestContext('fake', 'fake', auth_token=True)
api_v2 = openstack_api.FaultWrapper(api_auth.InjectContext(ctxt,
limits.RateLimitingMiddleware(
serialization(
extensions.ExtensionMiddleware(inner_app_v2)))))
limits.RateLimitingMiddleware(inner_app_v2)))
elif use_no_auth:
api_v2 = openstack_api.FaultWrapper(auth.NoAuthMiddleware(
limits.RateLimitingMiddleware(
serialization(
extensions.ExtensionMiddleware(inner_app_v2)))))
limits.RateLimitingMiddleware(inner_app_v2)))
else:
api_v2 = openstack_api.FaultWrapper(auth.AuthMiddleware(
limits.RateLimitingMiddleware(
serialization(
extensions.ExtensionMiddleware(inner_app_v2)))))
limits.RateLimitingMiddleware(inner_app_v2)))
mapper = urlmap.URLMap()
mapper['/v2'] = api_v2

View File

@@ -372,7 +372,7 @@ class MetadataXMLDeserializationTest(test.TestCase):
class MetadataXMLSerializationTest(test.TestCase):
def test_xml_declaration(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
'one': 'two',
@@ -380,20 +380,20 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture, 'index')
output = serializer.serialize(fixture)
print output
has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
self.assertTrue(has_dec)
def test_index(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
'one': 'two',
'three': 'four',
},
}
output = serializer.serialize(fixture, 'index')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
@@ -406,13 +406,13 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
def test_index_null(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
None: None,
},
}
output = serializer.serialize(fixture, 'index')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
@@ -425,13 +425,13 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
def test_index_unicode(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
u'three': u'Jos\xe9',
},
}
output = serializer.serialize(fixture, 'index')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
@@ -444,13 +444,13 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(metadata_elem.text.strip(), meta_value)
def test_show(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetaItemTemplate()
fixture = {
'meta': {
'one': 'two',
},
}
output = serializer.serialize(fixture, 'show')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
meta_dict = fixture['meta']
@@ -459,14 +459,14 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(root.text.strip(), meta_value)
def test_update_all(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
'key6': 'value6',
'key4': 'value4',
},
}
output = serializer.serialize(fixture, 'update_all')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
@@ -479,13 +479,13 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(str(metadata_elem.text).strip(), str(meta_value))
def test_update_item(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetaItemTemplate()
fixture = {
'meta': {
'one': 'two',
},
}
output = serializer.serialize(fixture, 'update')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
meta_dict = fixture['meta']
@@ -494,7 +494,7 @@ class MetadataXMLSerializationTest(test.TestCase):
self.assertEqual(root.text.strip(), meta_value)
def test_create(self):
serializer = common.MetadataXMLSerializer()
serializer = common.MetadataTemplate()
fixture = {
'metadata': {
'key9': 'value9',
@@ -502,7 +502,7 @@ class MetadataXMLSerializationTest(test.TestCase):
'key1': 'value1',
},
}
output = serializer.serialize(fixture, 'create')
output = serializer.serialize(fixture)
print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
@@ -524,8 +524,3 @@ class MetadataXMLSerializationTest(test.TestCase):
""".replace(" ", "").replace("\n", ""))
self.assertEqual(expected.toxml(), actual.toxml())
def test_delete(self):
serializer = common.MetadataXMLSerializer()
output = serializer.serialize(None, 'delete')
self.assertEqual(output, '')

View File

@@ -98,29 +98,6 @@ class ActionDispatcherTest(test.TestCase):
self.assertEqual(serializer.dispatch({}, action='update'), 'trousers')
class ResponseHeadersSerializerTest(test.TestCase):
def test_default(self):
serializer = wsgi.ResponseHeadersSerializer()
context = nova.context.get_admin_context()
req = webob.Request.blank('/', environ={'nova.context': context})
response = webob.Response(request=req)
serializer.serialize(response, {'v': '123'}, 'asdf')
self.assertEqual(response.status_int, 200)
def test_custom(self):
class Serializer(wsgi.ResponseHeadersSerializer):
def update(self, response, data):
response.status_int = 404
response.headers['X-Custom-Header'] = data['v']
serializer = Serializer()
context = nova.context.get_admin_context()
req = webob.Request.blank('/', environ={'nova.context': context})
response = webob.Response(request=req)
serializer.serialize(response, {'v': '123'}, 'update')
self.assertEqual(response.status_int, 404)
self.assertEqual(response.headers['X-Custom-Header'], '123')
class DictSerializerTest(test.TestCase):
def test_dispatch_default(self):
serializer = wsgi.DictSerializer()
@@ -207,226 +184,6 @@ class XMLDeserializerTest(test.TestCase):
self.assertEqual(deserializer.deserialize(xml), as_dict)
class RequestHeadersDeserializerTest(test.TestCase):
def test_default(self):
deserializer = wsgi.RequestHeadersDeserializer()
req = wsgi.Request.blank('/')
self.assertEqual(deserializer.deserialize(req, 'asdf'), {})
def test_custom(self):
class Deserializer(wsgi.RequestHeadersDeserializer):
def update(self, request):
return {'a': request.headers['X-Custom-Header']}
deserializer = Deserializer()
req = wsgi.Request.blank('/')
req.headers['X-Custom-Header'] = 'b'
self.assertEqual(deserializer.deserialize(req, 'update'), {'a': 'b'})
class ResponseHeadersSerializerTest(test.TestCase):
def test_request_id(self):
serializer = wsgi.ResponseHeadersSerializer()
context = nova.context.get_admin_context()
req = webob.Request.blank('/', environ={'nova.context': context})
res = webob.Response(request=req)
serializer.serialize(res, {}, 'foo')
h1 = res.headers.get('X-Compute-Request-Id')
self.assertTrue(h1)
context = nova.context.get_admin_context()
req = webob.Request.blank('/', environ={'nova.context': context})
res = webob.Response(request=req)
serializer.serialize(res, {}, 'foo')
h2 = res.headers.get('X-Compute-Request-Id')
self.assertTrue(h2)
self.assertNotEqual(h1, h2)
class JSONSerializer(object):
def serialize(self, data, action='default'):
return 'pew_json'
class XMLSerializer(object):
def serialize(self, data, action='default'):
return 'pew_xml'
class HeadersSerializer(object):
def serialize(self, response, data, action):
response.status_int = 404
class ResponseSerializerTest(test.TestCase):
def setUp(self):
self.body_serializers = {
'application/json': JSONSerializer(),
'application/xml': XMLSerializer(),
}
self.serializer = wsgi.ResponseSerializer(self.body_serializers,
HeadersSerializer())
def tearDown(self):
pass
def test_get_serializer(self):
ctype = 'application/json'
self.assertEqual(self.serializer.get_body_serializer(ctype),
self.body_serializers[ctype])
def test_get_serializer_unknown_content_type(self):
self.assertRaises(exception.InvalidContentType,
self.serializer.get_body_serializer,
'application/unknown')
def test_serialize_response_json(self):
for content_type in ('application/json',
'application/vnd.openstack.compute+json'):
request = wsgi.Request.blank('/')
response = self.serializer.serialize(request, {}, content_type)
self.assertEqual(response.headers['Content-Type'], content_type)
self.assertEqual(response.body, 'pew_json')
self.assertEqual(response.status_int, 404)
def test_serialize_response_xml(self):
for content_type in ('application/xml',
'application/vnd.openstack.compute+xml'):
request = wsgi.Request.blank('/')
response = self.serializer.serialize(request, {}, content_type)
self.assertEqual(response.headers['Content-Type'], content_type)
self.assertEqual(response.body, 'pew_xml')
self.assertEqual(response.status_int, 404)
def test_serialize_response_None(self):
request = wsgi.Request.blank('/')
response = self.serializer.serialize(request, None, 'application/json')
self.assertEqual(response.headers['Content-Type'], 'application/json')
self.assertEqual(response.body, '')
self.assertEqual(response.status_int, 404)
def test_serialize_response_dict_to_unknown_content_type(self):
request = wsgi.Request.blank('/')
self.assertRaises(exception.InvalidContentType,
self.serializer.serialize,
request, {}, 'application/unknown')
class LazySerializationTest(test.TestCase):
def setUp(self):
self.body_serializers = {
'application/json': JSONSerializer(),
'application/xml': XMLSerializer(),
}
self.serializer = wsgi.ResponseSerializer(self.body_serializers,
HeadersSerializer())
def tearDown(self):
pass
def test_serialize_response_json(self):
for content_type in ('application/json',
'application/vnd.openstack.compute+json'):
request = wsgi.Request.blank('/')
request.environ['nova.lazy_serialize'] = True
response = self.serializer.serialize(request, {}, content_type)
self.assertEqual(response.headers['Content-Type'], content_type)
self.assertEqual(response.status_int, 404)
body = json.loads(response.body)
self.assertEqual(body, {})
serializer = request.environ['nova.serializer']
self.assertEqual(serializer.serialize(body), 'pew_json')
def test_serialize_response_xml(self):
for content_type in ('application/xml',
'application/vnd.openstack.compute+xml'):
request = wsgi.Request.blank('/')
request.environ['nova.lazy_serialize'] = True
response = self.serializer.serialize(request, {}, content_type)
self.assertEqual(response.headers['Content-Type'], content_type)
self.assertEqual(response.status_int, 404)
body = json.loads(response.body)
self.assertEqual(body, {})
serializer = request.environ['nova.serializer']
self.assertEqual(serializer.serialize(body), 'pew_xml')
def test_serialize_response_None(self):
request = wsgi.Request.blank('/')
request.environ['nova.lazy_serialize'] = True
response = self.serializer.serialize(request, None, 'application/json')
self.assertEqual(response.headers['Content-Type'], 'application/json')
self.assertEqual(response.status_int, 404)
self.assertEqual(response.body, '')
class RequestDeserializerTest(test.TestCase):
def setUp(self):
class JSONDeserializer(object):
def deserialize(self, data, action='default'):
return 'pew_json'
class XMLDeserializer(object):
def deserialize(self, data, action='default'):
return 'pew_xml'
self.body_deserializers = {
'application/json': JSONDeserializer(),
'application/xml': XMLDeserializer(),
}
self.deserializer = wsgi.RequestDeserializer(self.body_deserializers)
def tearDown(self):
pass
def test_get_deserializer(self):
ctype = 'application/json'
expected = self.deserializer.get_body_deserializer(ctype)
self.assertEqual(expected, self.body_deserializers[ctype])
def test_get_deserializer_unknown_content_type(self):
self.assertRaises(exception.InvalidContentType,
self.deserializer.get_body_deserializer,
'application/unknown')
def test_get_expected_content_type(self):
ctype = 'application/json'
request = wsgi.Request.blank('/')
request.headers['Accept'] = ctype
self.assertEqual(self.deserializer.get_expected_content_type(request),
ctype)
def test_get_action_args(self):
env = {
'wsgiorg.routing_args': [None, {
'controller': None,
'format': None,
'action': 'update',
'id': 12,
}],
}
expected = {'action': 'update', 'id': 12}
self.assertEqual(self.deserializer.get_action_args(env), expected)
def test_deserialize(self):
def fake_get_routing_args(request):
return {'action': 'create'}
self.deserializer.get_action_args = fake_get_routing_args
request = wsgi.Request.blank('/')
request.headers['Accept'] = 'application/xml'
deserialized = self.deserializer.deserialize(request)
expected = ('create', {}, 'application/xml')
self.assertEqual(expected, deserialized)
class ResourceTest(test.TestCase):
def test_resource_call(self):
class Controller(object):

View File

@@ -712,78 +712,6 @@ class TemplateBuilderTest(test.TestCase):
self.assertEqual(tmpl1, tmpl2)
class SerializerTest(xmlutil.XMLTemplateSerializer):
def test(self):
root = xmlutil.TemplateElement('servers')
a = xmlutil.SubTemplateElement(root, 'a', selector='servers')
a.text = xmlutil.Selector('a')
return xmlutil.MasterTemplate(root, 1, nsmap={None: "asdf"})
class XMLTemplateSerializerTest(test.TestCase):
def setUp(self):
self.tmpl_serializer = SerializerTest()
self.data = dict(servers=dict(a=(2, 3)))
self.data_multi = dict(servers=[dict(a=(2, 3)), dict(a=(3, 4))])
super(XMLTemplateSerializerTest, self).setUp()
def test_get_template(self):
# First, check what happens when we fall back on the default
# option
self.assertEqual(self.tmpl_serializer.get_template(), None)
self.assertEqual(self.tmpl_serializer.get_template('nosuch'), None)
# Now, check that we get back a template
tmpl = self.tmpl_serializer.get_template('test')
self.assertNotEqual(tmpl, None)
self.assertEqual(tmpl.root.tag, 'servers')
def test_serialize_default(self):
expected_xml = '<servers><a>(2,3)</a></servers>'
result = self.tmpl_serializer.serialize(self.data)
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
def test_serialize_multi_default(self):
expected_xml = ('<servers><server><a>(2,3)</a></server>'
'<server><a>(3,4)</a></server></servers>')
result = self.tmpl_serializer.serialize(self.data_multi)
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
def test_serialize_explicit(self):
expected_xml = ("<?xmlversion='1.0'encoding='UTF-8'?>"
'<serversxmlns="asdf"><a>(2,3)</a></servers>')
tmpl = self.tmpl_serializer.get_template('test')
result = self.tmpl_serializer.serialize(self.data, template=tmpl)
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
def test_serialize_multi_explicit(self):
expected_xml = ("<?xmlversion='1.0'encoding='UTF-8'?>"
'<serversxmlns="asdf"><a>(2,3)</a>'
'<a>(3,4)</a></servers>')
tmpl = self.tmpl_serializer.get_template('test')
result = self.tmpl_serializer.serialize(self.data_multi, template=tmpl)
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
def test_serialize(self):
expected_xml = ("<?xmlversion='1.0'encoding='UTF-8'?>"
'<serversxmlns="asdf"><a>(2,3)</a></servers>')
result = self.tmpl_serializer.serialize(self.data, 'test')
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
def test_serialize_multi(self):
expected_xml = ("<?xmlversion='1.0'encoding='UTF-8'?>"
'<serversxmlns="asdf"><a>(2,3)</a>'
'<a>(3,4)</a></servers>')
result = self.tmpl_serializer.serialize(self.data_multi, 'test')
result = result.replace('\n', '').replace(' ', '')
self.assertEqual(result, expected_xml)
class MiscellaneousXMLUtilTests(test.TestCase):
def test_make_flat_dict(self):
expected_xml = ("<?xml version='1.0' encoding='UTF-8'?>\n"

View File

@@ -251,7 +251,7 @@ class SnapshotSerializerTest(test.TestCase):
self.assertEqual(str(snap[attr]), tree.get(attr))
def test_snapshot_show_create_serializer(self):
serializer = snapshots.SnapshotSerializer()
serializer = snapshots.SnapshotTemplate()
raw_snapshot = dict(
id='snap_id',
status='snap_status',
@@ -261,7 +261,7 @@ class SnapshotSerializerTest(test.TestCase):
displayDescription='snap_desc',
volumeId='vol_id',
)
text = serializer.serialize(dict(snapshot=raw_snapshot), 'show')
text = serializer.serialize(dict(snapshot=raw_snapshot))
print text
tree = etree.fromstring(text)
@@ -269,7 +269,7 @@ class SnapshotSerializerTest(test.TestCase):
self._verify_snapshot(raw_snapshot, tree)
def test_snapshot_index_detail_serializer(self):
serializer = snapshots.SnapshotSerializer()
serializer = snapshots.SnapshotsTemplate()
raw_snapshots = [dict(
id='snap1_id',
status='snap1_status',
@@ -288,7 +288,7 @@ class SnapshotSerializerTest(test.TestCase):
displayDescription='snap2_desc',
volumeId='vol2_id',
)]
text = serializer.serialize(dict(snapshots=raw_snapshots), 'index')
text = serializer.serialize(dict(snapshots=raw_snapshots))
print text
tree = etree.fromstring(text)

View File

@@ -123,10 +123,6 @@ class VolumeTypesApiTest(test.TestCase):
class VolumeTypesSerializerTest(test.TestCase):
def setUp(self):
super(VolumeTypesSerializerTest, self).setUp()
self.serializer = types.VolumeTypesSerializer()
def _verify_volume_type(self, vtype, tree):
self.assertEqual('volume_type', tree.tag)
self.assertEqual(vtype['name'], tree.get('name'))
@@ -142,9 +138,11 @@ class VolumeTypesSerializerTest(test.TestCase):
self.assertEqual(len(seen), 0)
def test_index_serializer(self):
serializer = types.VolumeTypesTemplate()
# Just getting some input data
vtypes = return_volume_types_get_all_types(None)
text = self.serializer.serialize(vtypes, 'index')
text = serializer.serialize(vtypes)
print text
tree = etree.fromstring(text)
@@ -157,8 +155,10 @@ class VolumeTypesSerializerTest(test.TestCase):
self._verify_volume_type(vtypes[name], child)
def test_voltype_serializer(self):
serializer = types.VolumeTypeTemplate()
vtype = stub_volume_type(1)
text = self.serializer.serialize(dict(volume_type=vtype))
text = serializer.serialize(dict(volume_type=vtype))
print text
tree = etree.fromstring(text)

View File

@@ -134,47 +134,8 @@ class VolumeSerializerTest(test.TestCase):
not_seen.remove(gr_child.tag)
self.assertEqual(0, len(not_seen))
def test_attach_show_create_serializer(self):
serializer = volumes.VolumeAttachmentSerializer()
raw_attach = dict(
id='vol_id',
volumeId='vol_id',
serverId='instance_uuid',
device='/foo')
text = serializer.serialize(dict(volumeAttachment=raw_attach), 'show')
print text
tree = etree.fromstring(text)
self.assertEqual('volumeAttachment', tree.tag)
self._verify_volume_attachment(raw_attach, tree)
def test_attach_index_serializer(self):
serializer = volumes.VolumeAttachmentSerializer()
raw_attaches = [dict(
id='vol_id1',
volumeId='vol_id1',
serverId='instance1_uuid',
device='/foo1'),
dict(
id='vol_id2',
volumeId='vol_id2',
serverId='instance2_uuid',
device='/foo2')]
text = serializer.serialize(dict(volumeAttachments=raw_attaches),
'index')
print text
tree = etree.fromstring(text)
self.assertEqual('volumeAttachments', tree.tag)
self.assertEqual(len(raw_attaches), len(tree))
for idx, child in enumerate(tree):
self.assertEqual('volumeAttachment', child.tag)
self._verify_volume_attachment(raw_attaches[idx], child)
def test_volume_show_create_serializer(self):
serializer = volumes.VolumeSerializer()
serializer = volumes.VolumeTemplate()
raw_volume = dict(
id='vol_id',
status='vol_status',
@@ -195,7 +156,7 @@ class VolumeSerializerTest(test.TestCase):
baz='quux',
),
)
text = serializer.serialize(dict(volume=raw_volume), 'show')
text = serializer.serialize(dict(volume=raw_volume))
print text
tree = etree.fromstring(text)
@@ -203,7 +164,7 @@ class VolumeSerializerTest(test.TestCase):
self._verify_volume(raw_volume, tree)
def test_volume_index_detail_serializer(self):
serializer = volumes.VolumeSerializer()
serializer = volumes.VolumesTemplate()
raw_volumes = [dict(
id='vol1_id',
status='vol1_status',
@@ -244,7 +205,7 @@ class VolumeSerializerTest(test.TestCase):
bar='vol2_bar',
),
)]
text = serializer.serialize(dict(volumes=raw_volumes), 'index')
text = serializer.serialize(dict(volumes=raw_volumes))
print text
tree = etree.fromstring(text)

View File

@@ -27,8 +27,6 @@ LOG = logging.getLogger('nova.tests.integrated')
class ExtensionsTest(integrated_helpers._IntegratedTestBase):
def _get_flags(self):
extensions.ExtensionManager.reset()
f = super(ExtensionsTest, self)._get_flags()
f['osapi_compute_extension'] = FLAGS.osapi_compute_extension[:]
f['osapi_compute_extension'].append(