summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorKevin L. Mitchell <kevin.mitchell@rackspace.com>2012-01-16 11:31:56 -0600
committerKevin L. Mitchell <kevin.mitchell@rackspace.com>2012-01-16 11:31:56 -0600
commite022ea9bb44cd49b45e6d4b82dd168000988dc20 (patch)
tree9bba4ee2fb791fe123dc9d5013403b4c760f35be /nova/api
parent312caea8ab278882552cf9006653de97ced88ef8 (diff)
downloadnova-e022ea9bb44cd49b45e6d4b82dd168000988dc20.tar.gz
nova-e022ea9bb44cd49b45e6d4b82dd168000988dc20.tar.xz
nova-e022ea9bb44cd49b45e6d4b82dd168000988dc20.zip
Update some extensions (2)
Updates the extended_status (ExtendedStatus) extension to conform to the new extension interface. Related to blueprint extension-refactor. Change-Id: Ie00968c4cdcd67a2cf659a2b8c2ca2b31e8dcc9d
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/compute/contrib/extended_status.py142
-rw-r--r--nova/api/openstack/wsgi.py45
2 files changed, 110 insertions, 77 deletions
diff --git a/nova/api/openstack/compute/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py
index 7f9301b93..7479d6f00 100644
--- a/nova/api/openstack/compute/contrib/extended_status.py
+++ b/nova/api/openstack/compute/contrib/extended_status.py
@@ -17,6 +17,7 @@
from webob import exc
from nova.api.openstack import extensions
+from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
from nova import compute
from nova import exception
@@ -28,6 +29,55 @@ FLAGS = flags.FLAGS
LOG = logging.getLogger("nova.api.openstack.compute.contrib.extendedstatus")
+class ExtendedStatusController(wsgi.Controller):
+ def __init__(self, *args, **kwargs):
+ super(ExtendedStatusController, self).__init__(*args, **kwargs)
+ self.compute_api = compute.API()
+
+ def _get_and_extend_one(self, context, server_id, body):
+ try:
+ inst_ref = self.compute_api.routing_get(context, server_id)
+ except exception.NotFound:
+ LOG.warn("Instance %s not found" % server_id)
+ raise
+
+ for state in ['task_state', 'vm_state', 'power_state']:
+ key = "%s:%s" % (Extended_status.alias, state)
+ body[key] = inst_ref[state]
+
+ @wsgi.extends
+ def show(self, req, resp_obj, id):
+ context = req.environ['nova.context']
+
+ # Attach our slave template to the response object
+ resp_obj.attach(xml=ExtendedStatusTemplate())
+
+ try:
+ self._get_and_extend_one(context, id, resp_obj.obj['server'])
+ except exception.NotFound:
+ explanation = _("Server not found.")
+ raise exc.HTTPNotFound(explanation=explanation)
+
+ @wsgi.extends
+ def detail(self, req, resp_obj):
+ context = req.environ['nova.context']
+
+ # Attach our slave template to the response object
+ resp_obj.attach(xml=ExtendedStatusesTemplate())
+
+ for server in list(resp_obj.obj['servers']):
+ try:
+ self._get_and_extend_one(context, server['id'], server)
+ except exception.NotFound:
+ # NOTE(dtroyer): A NotFound exception at this point
+ # happens because a delete was in progress and the
+ # server that was present in the original call to
+ # compute.api.get_all() is no longer present.
+ # Delete it from the response and move on.
+ resp_obj.obj['servers'].remove(server)
+ continue
+
+
class Extended_status(extensions.ExtensionDescriptor):
"""Extended Status support"""
@@ -38,79 +88,33 @@ class Extended_status(extensions.ExtensionDescriptor):
updated = "2011-11-03T00:00:00+00:00"
admin_only = True
- def get_request_extensions(self):
- request_extensions = []
+ def get_controller_extensions(self):
+ controller = ExtendedStatusController()
+ extension = extensions.ControllerExtension(self, 'servers', controller)
+ return [extension]
- def _get_and_extend_one(context, server_id, body):
- compute_api = compute.API()
- try:
- inst_ref = compute_api.routing_get(context, server_id)
- except exception.NotFound:
- LOG.warn("Instance %s not found (one)" % server_id)
- explanation = _("Server not found.")
- raise exc.HTTPNotFound(explanation=explanation)
-
- for state in ['task_state', 'vm_state', 'power_state']:
- key = "%s:%s" % (Extended_status.alias, state)
- body['server'][key] = inst_ref[state]
-
- def _get_and_extend_all(context, body):
- # TODO(mdietz): This is a brilliant argument for this to *not*
- # be an extension. The problem is we either have to 1) duplicate
- # the logic from the servers controller or 2) do what we did
- # and iterate over the list of potentially sorted, limited
- # and whatever else elements and find each individual.
- compute_api = compute.API()
-
- for server in list(body['servers']):
- try:
- inst_ref = compute_api.routing_get(context, server['id'])
- except exception.NotFound:
- # NOTE(dtroyer): A NotFound exception at this point
- # happens because a delete was in progress and the
- # server that was present in the original call to
- # compute.api.get_all() is no longer present.
- # Delete it from the response and move on.
- LOG.warn("Instance %s not found (all)" % server['id'])
- body['servers'].remove(server)
- continue
-
- #TODO(bcwaldon): these attributes should be prefixed with
- # something specific to this extension
- for state in ['task_state', 'vm_state', 'power_state']:
- key = "%s:%s" % (Extended_status.alias, state)
- server[key] = inst_ref[state]
-
- def _extended_status_handler(req, res, body):
- context = req.environ['nova.context']
- server_id = req.environ['wsgiorg.routing_args'][1].get('id')
-
- if 'nova.template' in req.environ:
- tmpl = req.environ['nova.template']
- tmpl.attach(ExtendedStatusTemplate())
-
- if server_id:
- _get_and_extend_one(context, server_id, body)
- else:
- _get_and_extend_all(context, body)
- return res
-
- req_ext = extensions.RequestExtension('GET',
- '/:(project_id)/servers/:(id)',
- _extended_status_handler)
- request_extensions.append(req_ext)
-
- return request_extensions
+
+def make_server(elem):
+ elem.set('{%s}task_state' % Extended_status.namespace,
+ '%s:task_state' % Extended_status.alias)
+ elem.set('{%s}power_state' % Extended_status.namespace,
+ '%s:power_state' % Extended_status.alias)
+ elem.set('{%s}vm_state' % Extended_status.namespace,
+ '%s:vm_state' % Extended_status.alias)
class ExtendedStatusTemplate(xmlutil.TemplateBuilder):
def construct(self):
- root = xmlutil.TemplateElement('server')
- root.set('{%s}task_state' % Extended_status.namespace,
- '%s:task_state' % Extended_status.alias)
- root.set('{%s}power_state' % Extended_status.namespace,
- '%s:power_state' % Extended_status.alias)
- root.set('{%s}vm_state' % Extended_status.namespace,
- '%s:vm_state' % Extended_status.alias)
+ root = xmlutil.TemplateElement('server', selector='server')
+ make_server(root)
+ return xmlutil.SlaveTemplate(root, 1, nsmap={
+ Extended_status.alias: Extended_status.namespace})
+
+
+class ExtendedStatusesTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ root = xmlutil.TemplateElement('servers')
+ elem = xmlutil.SubTemplateElement(root, 'server', selector='servers')
+ make_server(elem)
return xmlutil.SlaveTemplate(root, 1, nsmap={
Extended_status.alias: Extended_status.namespace})
diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py
index defb26e6e..3bf1bef00 100644
--- a/nova/api/openstack/wsgi.py
+++ b/nova/api/openstack/wsgi.py
@@ -603,6 +603,8 @@ class ResponseObject(object):
self._default_code = 200
self._code = code
self._headers = {}
+ self.serializer = None
+ self.media_type = None
def __getitem__(self, key):
"""Retrieves a header with the given name."""
@@ -651,12 +653,31 @@ class ResponseObject(object):
try:
mtype = _MEDIA_TYPE_MAP.get(content_type, content_type)
if mtype in self.serializers:
- return self.serializers[mtype]
+ return mtype, self.serializers[mtype]
else:
- return default_serializers[mtype]
+ return mtype, default_serializers[mtype]
except (KeyError, TypeError):
raise exception.InvalidContentType(content_type=content_type)
+ def preserialize(self, content_type, default_serializers=None):
+ """Prepares the serializer that will be used to serialize.
+
+ Determines the serializer that will be used and prepares an
+ instance of it for later call. This allows the serializer to
+ be accessed by extensions for, e.g., template extension.
+ """
+
+ mtype, serializer = self.get_serializer(content_type,
+ default_serializers)
+ self.media_type = mtype
+ self.serializer = serializer()
+
+ def attach(self, **kwargs):
+ """Attach slave templates to serializers."""
+
+ if self.media_type in kwargs:
+ self.serializer.attach(kwargs[self.media_type])
+
def serialize(self, request, content_type, default_serializers=None):
"""Serializes the wrapped object.
@@ -664,7 +685,12 @@ class ResponseObject(object):
webob.Response object.
"""
- serializer = self.get_serializer(content_type, default_serializers)()
+ if self.serializer:
+ serializer = self.serializer
+ else:
+ _mtype, _serializer = self.get_serializer(content_type,
+ default_serializers)
+ serializer = _serializer()
response = webob.Response()
response.status_int = self.code
@@ -1030,6 +1056,14 @@ class Resource(wsgi.Application):
# Run post-processing extensions
if resp_obj:
+ # Do a preserialize to set up the response object
+ serializers = getattr(meth, 'wsgi_serializers', {})
+ resp_obj._bind_method_serializers(serializers)
+ if hasattr(meth, 'wsgi_code'):
+ resp_obj._default_code = meth.wsgi_code
+ resp_obj.preserialize(accept, self.default_serializers)
+
+ # Process post-processing extensions
response = self.post_process_extensions(post, resp_obj,
request, action_args)
@@ -1040,11 +1074,6 @@ class Resource(wsgi.Application):
accept,
action=action)
else:
- serializers = getattr(meth, 'wsgi_serializers', {})
- resp_obj._bind_method_serializers(serializers)
- if hasattr(meth, 'wsgi_code'):
- resp_obj._default_code = meth.wsgi_code
-
response = resp_obj.serialize(request, accept,
self.default_serializers)