Merge "Remove deprecated extension code."

This commit is contained in:
Jenkins
2012-01-23 22:13:36 +00:00
committed by Gerrit Code Review
30 changed files with 275 additions and 1318 deletions

View File

@@ -93,12 +93,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
@@ -112,15 +112,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):
@@ -190,10 +189,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.
@@ -219,10 +216,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)
@@ -236,18 +231,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
@@ -271,11 +263,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
@@ -298,10 +288,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):
@@ -309,10 +297,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)
@@ -321,10 +307,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)
@@ -333,11 +317,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)
@@ -354,10 +336,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)
@@ -394,10 +374,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)
@@ -405,8 +383,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)
@@ -414,8 +391,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)
@@ -423,8 +399,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)
@@ -434,13 +409,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):
@@ -495,35 +468,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
@@ -612,7 +580,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',
@@ -626,7 +594,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']
@@ -645,7 +613,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",
@@ -671,7 +639,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(