27
27
from nova import exception
28
28
from nova import flags
29
29
from nova import log as logging
30
from nova import wsgi as base_wsgi
31
31
from nova.api.openstack import common
32
32
from nova.api.openstack import faults
33
from nova.api.openstack import wsgi
35
36
LOG = logging.getLogger('extensions')
116
117
return response_exts
119
class ActionExtensionController(common.OpenstackController):
120
class ActionExtensionController(object):
121
121
def __init__(self, application):
123
122
self.application = application
124
123
self.action_handlers = {}
126
125
def add_action(self, action_name, handler):
127
126
self.action_handlers[action_name] = handler
129
def action(self, req, id):
131
input_dict = self._deserialize(req.body, req.get_content_type())
128
def action(self, req, id, body):
132
129
for action_name, handler in self.action_handlers.iteritems():
133
if action_name in input_dict:
134
return handler(input_dict, req, id)
130
if action_name in body:
131
return handler(body, req, id)
135
132
# no action handler found (bump to downstream application)
136
133
res = self.application
140
class ResponseExtensionController(common.OpenstackController):
137
class ActionExtensionResource(wsgi.Resource):
139
def __init__(self, application):
140
controller = ActionExtensionController(application)
141
super(ActionExtensionResource, self).__init__(controller)
143
def add_action(self, action_name, handler):
144
self.controller.add_action(action_name, handler)
147
class ResponseExtensionController(object):
142
149
def __init__(self, application):
143
150
self.application = application
157
164
headers = res.headers
158
165
except AttributeError:
159
166
default_xmlns = None
160
body = self._serialize(res, content_type, default_xmlns)
168
'application/xml': wsgi.XMLSerializer(),
169
'application/json': wsgi.JSONSerializer(),
171
body = serializer.serialize(res)
161
172
headers = {"Content-Type": content_type}
162
173
res = webob.Response()
168
class ExtensionController(common.OpenstackController):
179
class ResponseExtensionResource(wsgi.Resource):
181
def __init__(self, application):
182
controller = ResponseExtensionController(application)
183
super(ResponseExtensionResource, self).__init__(controller)
185
def add_handler(self, handler):
186
self.controller.add_handler(handler)
189
class ExtensionController(object):
170
191
def __init__(self, extension_manager):
171
192
self.extension_manager = extension_manager
198
219
raise faults.Fault(webob.exc.HTTPNotFound())
201
class ExtensionMiddleware(wsgi.Middleware):
222
class ExtensionMiddleware(base_wsgi.Middleware):
202
223
"""Extensions middleware for WSGI."""
204
225
def factory(cls, global_config, **local_config):
207
228
return cls(app, **local_config)
210
def _action_ext_controllers(self, application, ext_mgr, mapper):
211
"""Return a dict of ActionExtensionController-s by collection."""
212
action_controllers = {}
231
def _action_ext_resources(self, application, ext_mgr, mapper):
232
"""Return a dict of ActionExtensionResource objects by collection."""
233
action_resources = {}
213
234
for action in ext_mgr.get_actions():
214
if not action.collection in action_controllers.keys():
215
controller = ActionExtensionController(application)
235
if not action.collection in action_resources.keys():
236
resource = ActionExtensionResource(application)
216
237
mapper.connect("/%s/:(id)/action.:(format)" %
217
238
action.collection,
219
controller=controller,
220
241
conditions=dict(method=['POST']))
221
242
mapper.connect("/%s/:(id)/action" % action.collection,
223
controller=controller,
224
245
conditions=dict(method=['POST']))
225
action_controllers[action.collection] = controller
227
return action_controllers
229
def _response_ext_controllers(self, application, ext_mgr, mapper):
230
"""Returns a dict of ResponseExtensionController-s by collection."""
231
response_ext_controllers = {}
246
action_resources[action.collection] = resource
248
return action_resources
250
def _response_ext_resources(self, application, ext_mgr, mapper):
251
"""Returns a dict of ResponseExtensionResource objects by collection."""
252
response_ext_resources = {}
232
253
for resp_ext in ext_mgr.get_response_extensions():
233
if not resp_ext.key in response_ext_controllers.keys():
234
controller = ResponseExtensionController(application)
254
if not resp_ext.key in response_ext_resources.keys():
255
resource = ResponseExtensionResource(application)
235
256
mapper.connect(resp_ext.url_route + '.:(format)',
236
257
action='process',
237
controller=controller,
238
259
conditions=resp_ext.conditions)
240
261
mapper.connect(resp_ext.url_route,
241
262
action='process',
242
controller=controller,
243
264
conditions=resp_ext.conditions)
244
response_ext_controllers[resp_ext.key] = controller
265
response_ext_resources[resp_ext.key] = resource
246
return response_ext_controllers
267
return response_ext_resources
248
269
def __init__(self, application, ext_mgr=None):
258
279
LOG.debug(_('Extended resource: %s'),
259
280
resource.collection)
260
281
mapper.resource(resource.collection, resource.collection,
261
controller=resource.controller,
282
controller=wsgi.Resource(resource.controller),
262
283
collection=resource.collection_actions,
263
284
member=resource.member_actions,
264
285
parent_resource=resource.parent)
266
287
# extended actions
267
action_controllers = self._action_ext_controllers(application, ext_mgr,
288
action_resources = self._action_ext_resources(application, ext_mgr,
269
290
for action in ext_mgr.get_actions():
270
291
LOG.debug(_('Extended action: %s'), action.action_name)
271
controller = action_controllers[action.collection]
272
controller.add_action(action.action_name, action.handler)
292
resource = action_resources[action.collection]
293
resource.add_action(action.action_name, action.handler)
274
295
# extended responses
275
resp_controllers = self._response_ext_controllers(application, ext_mgr,
296
resp_controllers = self._response_ext_resources(application, ext_mgr,
277
298
for response_ext in ext_mgr.get_response_extensions():
278
299
LOG.debug(_('Extended response: %s'), response_ext.key)
424
445
class ResponseExtension(object):
425
"""Add data to responses from core nova OpenStack API controllers."""
446
"""Add data to responses from core nova OpenStack API resources."""
427
448
def __init__(self, method, url_route, handler):
428
449
self.url_route = url_route
434
455
class ActionExtension(object):
435
"""Add custom actions to core nova OpenStack API controllers."""
456
"""Add custom actions to core nova OpenStack API resources."""
437
458
def __init__(self, collection, action_name, handler):
438
459
self.collection = collection