From d3c084f23448d1890bfda4a06de246f2be3c1279 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Mon, 17 Apr 2017 16:38:49 +0000 Subject: [PATCH] Register osapi_compute when nova-api is wsgi When the nova-api services starts from its own standalone binary it registers itself in the services table. The original wsgi script in nova/wsgi/nova-api.py did not, leading to the bug referenced below. The new wsgi script at nova.api.openstack.compute.wsgi, modelled on a similar thing used for the placement API, provides the necessary service registration. If a ServiceTooOld exception happens while trying to register the service then a very simple (currently very stubby) application is loaded instead of the compute api. This application returns a 500 and a message. Some caveats/todos: * wsgi apps managed under mod-wsgi (and presumably other containers) are not imported/compiled/run until the first request is made. In this case that means the service handling does not happen until that first request, somewhat defeating the purpose if the api is a bit idle. Change-Id: I7c4acfaa6c50ac0e4d6de69eb62ec5bbad72ff85 Closes-Bug: #1661360 --- nova/api/openstack/compute/wsgi.py | 86 ++++++++++++++++++++++++++++++ setup.cfg | 1 + 2 files changed, 87 insertions(+) create mode 100644 nova/api/openstack/compute/wsgi.py diff --git a/nova/api/openstack/compute/wsgi.py b/nova/api/openstack/compute/wsgi.py new file mode 100644 index 0000000000..154a00da3a --- /dev/null +++ b/nova/api/openstack/compute/wsgi.py @@ -0,0 +1,86 @@ +# 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. +"""WSGI script for Nova API, installed by pbr.""" + +import os + +from oslo_config import cfg +from oslo_log import log as logging +from paste import deploy + +from nova import config +from nova import context +from nova import exception +from nova import objects +from nova import service +from nova import utils + +CONF = cfg.CONF + +CONFIG_FILES = ['api-paste.ini', 'nova.conf'] +NAME = "osapi_compute" + +utils.monkey_patch() +objects.register_all() + + +def _get_config_files(env=None): + if env is None: + env = os.environ + dirname = env.get('OS_NOVA_CONFIG_DIR', '/etc/nova').strip() + return [os.path.join(dirname, config_file) + for config_file in CONFIG_FILES] + + +def _setup_service(host, name): + ctxt = context.get_admin_context() + service_ref = objects.Service.get_by_host_and_binary( + ctxt, host, name) + if service_ref: + service._update_service_ref(service_ref) + else: + try: + service_obj = objects.Service(ctxt) + service_obj.host = host + service_obj.binary = 'nova-%s' % name + service_obj.topic = None + service_obj.report_count = 0 + service_obj.create() + except (exception.ServiceTopicExists, + exception.ServiceBinaryExists): + # If we race to create a record with a sibling, don't + # fail here. + pass + + +def error_application(exc): + # TODO(cdent): make this something other than a stub + def application(environ, start_response): + start_response('500 Internal Server Error', [ + ('Content-Type', 'text/plain; charset=UTF-8')]) + return ['Out of date API service %s\n' % exc] + return application + + +def init_application(): + conf_files = _get_config_files() + config.parse_args([], default_config_files=conf_files) + + logging.setup(CONF, "nova") + try: + _setup_service(CONF.host, NAME) + except exception.ServiceTooOld as exc: + return error_application(exc) + + conf = conf_files[0] + + return deploy.loadapp('config:%s' % conf, name=NAME) diff --git a/setup.cfg b/setup.cfg index ee57afd104..3e2c3b200f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -69,6 +69,7 @@ console_scripts = nova-xvpvncproxy = nova.cmd.xvpvncproxy:main wsgi_scripts = nova-placement-api = nova.api.openstack.placement.wsgi:init_application + nova-api-wsgi = nova.api.openstack.compute.wsgi:init_application nova.api.v21.extensions = admin_actions = nova.api.openstack.compute.admin_actions:AdminActions