From 0973f558561173bdc84d7f4f8eb33da9fedafac2 Mon Sep 17 00:00:00 2001 From: Matt Dietz Date: Tue, 8 Nov 2011 14:12:46 -0600 Subject: Adds extended status information via the Admin API to the servers calls Change-Id: I294e64e878f1f6ebf33b83198abb2cdd8b6c5185 --- nova/api/openstack/contrib/extended_status.py | 110 ++++++++++++++++++++++++++ nova/api/openstack/wsgi.py | 2 +- 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 nova/api/openstack/contrib/extended_status.py (limited to 'nova/api') diff --git a/nova/api/openstack/contrib/extended_status.py b/nova/api/openstack/contrib/extended_status.py new file mode 100644 index 000000000..625f3ab2b --- /dev/null +++ b/nova/api/openstack/contrib/extended_status.py @@ -0,0 +1,110 @@ +# Copyright 2011 Openstack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""The Extended Status Admin API extension.""" + +import traceback + +import webob +from webob import exc + +from nova import compute +from nova import exception +from nova import flags +from nova import log as logging +from nova.api.openstack import extensions +from nova.api.openstack import faults +from nova.api.openstack import xmlutil + + +FLAGS = flags.FLAGS +LOG = logging.getLogger("nova.api.openstack.contrib.extendedstatus") + + +class Extended_status(extensions.ExtensionDescriptor): + """Extended Status support""" + + name = "ExtendedStatus" + alias = "OS-EXT-STS" + namespace = "http://docs.openstack.org/ext/extended_status/api/v1.1" + updated = "2011-11-03T00:00:00+00:00" + + def get_request_extensions(self): + request_extensions = [] + + 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: + 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 body['servers']: + try: + inst_ref = compute_api.routing_get(context, server['id']) + except exception.NotFound: + 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) + 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 + + if FLAGS.allow_admin_api: + req_ext = extensions.RequestExtension('GET', + '/:(project_id)/servers/:(id)', + _extended_status_handler) + request_extensions.append(req_ext) + + return request_extensions + + +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) + 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 f96a12eab..7deba6382 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -477,6 +477,7 @@ class ResponseSerializer(object): 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: @@ -512,7 +513,6 @@ class LazySerializationMiddleware(wsgi.Middleware): # Re-serialize the body response.body = serializer.serialize(utils.loads(response.body), **kwargs) - return response -- cgit