From 7aba2d5f8ae81a085ab96188f89a66e1fc693fe5 Mon Sep 17 00:00:00 2001 From: Hongbin Lu Date: Wed, 2 Aug 2017 02:20:12 +0000 Subject: [PATCH] Switch from mode_wsgi to uwsgi When the wsgi community goal was first approved, the push was to use mod_wsgi. mod_wsgi has many issues when being used in devstack for development or testing (see [1]). This commit will switch the deployment of zun-api to uwsgi. [1] https://governance.openstack.org/tc/goals/pike/deploy-api-in-wsgi .html#uwsgi-vs-mod-wsgi Change-Id: Iec05ccb8aceee6874e3c04280fe7596f8292e333 Closes-Bug: #1692382 --- devstack/lib/zun | 81 +++++++++-------------------- doc/source/contributor/mod-wsgi.rst | 53 +++++++++++++++++-- setup.cfg | 2 + zun/api/app.wsgi | 22 +------- zun/api/wsgi.py | 35 +++++++++++++ zun/tests/contrib/gate_hook.sh | 2 +- 6 files changed, 114 insertions(+), 81 deletions(-) create mode 100644 zun/api/wsgi.py diff --git a/devstack/lib/zun b/devstack/lib/zun index da7d97c1b..761fcea26 100644 --- a/devstack/lib/zun +++ b/devstack/lib/zun @@ -49,14 +49,8 @@ if is_ssl_enabled_service "zun" || is_service_enabled tls-proxy; then ZUN_SERVICE_PROTOCOL="https" fi -if is_suse; then - ZUN_WSGI_DIR=${ZUN_WSGI_DIR:-/srv/www/htdocs/zun} -else - ZUN_WSGI_DIR=${ZUN_WSGI_DIR:-/var/www/zun} -fi - -# Toggle for deploying ZUN-API under HTTPD + mod_wsgi -ZUN_USE_MOD_WSGI=${ZUN_USE_MOD_WSGI:-False} +# Toggle for deploying ZUN-API under a wsgi server +ZUN_USE_UWSGI=${ZUN_USE_UWSGI:-True} # Public facing bits @@ -74,6 +68,9 @@ else ZUN_BIN_DIR=$(get_python_exec_prefix) fi +ZUN_UWSGI=$ZUN_BIN_DIR/zun-api-wsgi +ZUN_UWSGI_CONF=$ZUN_CONF_DIR/zun-api-uwsgi.ini + DOCKER_REMOTE_API_PORT=2375 ZUN_DRIVER=${ZUN_DRIVER:-docker} ZUN_DB_TYPE=${ZUN_DB_TYPE:-sql} @@ -89,33 +86,6 @@ fi # Functions # --------- -# _cleanup_zun_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file -function _cleanup_zun_apache_wsgi { - sudo rm -f $ZUN_WSGI_DIR/* - sudo rm -f $(apache_site_config_for zun) -} - -# _config_zun_apache_wsgi() - Set WSGI config files of zun -function _config_zun_apache_wsgi { - - sudo mkdir -p $ZUN_WSGI_DIR - - local zun_apache_conf - zun_apache_conf=$(apache_site_config_for zun) - - # copy proxy vhost and wsgi helper files - sudo cp $ZUN_DIR/zun/api/app.wsgi $ZUN_WSGI_DIR/zun - - sudo cp $ZUN_DIR/etc/apache2/zun.conf.template $zun_apache_conf - - sudo sed -e " - s|%PUBLICPORT%|$ZUN_SERVICE_PORT|g; - s|%USER%|$STACK_USER|g; - s|%PUBLICWSGI%|$ZUN_WSGI_DIR/zun|g; - s|%APACHE_NAME%|$APACHE_NAME|g - " -i $zun_apache_conf -} - # Test if any zun services are enabled # is_zun_enabled function is_zun_enabled { @@ -136,9 +106,7 @@ function cleanup_zun { sudo docker rm -f $containers || true fi - if [ "$ZUN_USE_MOD_WSGI" == "True" ]; then - _cleanup_zun_apache_wsgi - fi + remove_uwsgi_config "$ZUN_UWSGI_CONF" "$ZUN_UWSGI" } # configure_zun() - Set config files, create data dirs, etc @@ -155,9 +123,7 @@ function configure_zun { create_api_paste_conf - if [ "$ZUN_USE_MOD_WSGI" == "True" ]; then - _config_zun_apache_wsgi - fi + write_uwsgi_config "$ZUN_UWSGI_CONF" "$ZUN_UWSGI" "/container" if [[ "$USE_PYTHON3" = "True" ]]; then # Switch off glance->swift communication as swift fails under py3.x @@ -184,13 +150,20 @@ function create_zun_accounts { if is_service_enabled zun-api; then + local zun_api_url + if [[ "$ZUN_USE_UWSGI" == "True" ]]; then + zun_api_url="$ZUN_SERVICE_PROTOCOL://$ZUN_SERVICE_HOST/container" + else + zun_api_url="$ZUN_SERVICE_PROTOCOL://$ZUN_SERVICE_HOST:$ZUN_SERVICE_PORT" + fi + local zun_service=$(get_or_create_service "zun" \ "container" "Container As Service") get_or_create_endpoint $zun_service \ "$REGION_NAME" \ - "$ZUN_SERVICE_PROTOCOL://$ZUN_SERVICE_HOST:$ZUN_SERVICE_PORT/v1" \ - "$ZUN_SERVICE_PROTOCOL://$ZUN_SERVICE_HOST:$ZUN_SERVICE_PORT/v1" \ - "$ZUN_SERVICE_PROTOCOL://$ZUN_SERVICE_HOST:$ZUN_SERVICE_PORT/v1" + "$zun_api_url/v1" \ + "$zun_api_url/v1" \ + "$zun_api_url/v1" fi } @@ -327,10 +300,6 @@ function install_zunclient { function install_zun { git_clone $ZUN_REPO $ZUN_DIR $ZUN_BRANCH setup_develop $ZUN_DIR - - if [ "$ZUN_USE_MOD_WSGI" == "True" ]; then - install_apache_wsgi - fi } function install_etcd_server { @@ -362,19 +331,17 @@ function start_zun_api { service_protocol="http" fi - local enabled_site_file - enabled_site_file=$(apache_site_config_for zun) - if [ -f ${enabled_site_file} ] && [ "$ZUN_USE_MOD_WSGI" == "True" ]; then - enable_apache_site zun - restart_apache_server - tail_log zun-api-access /var/log/$APACHE_NAME/zun_access.log - tail_log zun-api /var/log/$APACHE_NAME/zun_api.log + local zun_url + if [ "$ZUN_USE_UWSGI" == "True" ]; then + run_process zun-api "$ZUN_BIN_DIR/uwsgi --ini $ZUN_UWSGI_CONF" + zun_url=$service_protocol://$ZUN_SERVICE_HOST/container else run_process zun-api "$ZUN_BIN_DIR/zun-api" + zun_url=$service_protocol://$ZUN_SERVICE_HOST:$service_port fi echo "Waiting for zun-api to start..." - if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$ZUN_SERVICE_HOST:$service_port; then + if ! wait_for_service $SERVICE_TIMEOUT $zun_url; then die $LINENO "zun-api did not start" fi @@ -427,7 +394,7 @@ function stop_zun { stop_zun_etcd fi - if [ "$ZUN_USE_MOD_WSGI" == "True" ]; then + if [ "$ZUN_USE_UWSGI" == "True" ]; then disable_apache_site zun restart_apache_server else diff --git a/doc/source/contributor/mod-wsgi.rst b/doc/source/contributor/mod-wsgi.rst index 07a82351b..5a88a243e 100644 --- a/doc/source/contributor/mod-wsgi.rst +++ b/doc/source/contributor/mod-wsgi.rst @@ -11,9 +11,18 @@ License for the specific language governing permissions and limitations under the License. -=================================== - Installing the API behind mod_wsgi -=================================== +============================ + Installing the API via WSGI +============================ + +This document provides two WSGI deployments as examples: uwsgi and mod_wsgi. + +.. seealso:: + + https://governance.openstack.org/tc/goals/pike/deploy-api-in-wsgi.html#uwsgi-vs-mod-wsgi + +Installing the API behind mod_wsgi +================================== Zun comes with a few example files for configuring the API service to run behind Apache with ``mod_wsgi``. @@ -53,3 +62,41 @@ work with a copy of zun installed via devstack. On rpm-based systems:: $ service httpd reload + + +Installing the API with uwsgi +============================= + + +Create zun-uwsgi.ini file:: + + [uwsgi] + http = 0.0.0.0:9517 + wsgi-file = /zun/api/app.wsgi + plugins = python + # This is running standalone + master = true + # Set die-on-term & exit-on-reload so that uwsgi shuts down + exit-on-reload = true + die-on-term = true + # uwsgi recommends this to prevent thundering herd on accept. + thunder-lock = true + # Override the default size for headers from the 4k default. (mainly for keystone token) + buffer-size = 65535 + enable-threads = true + # Set the number of threads usually with the returns of command nproc + threads = 8 + # Make sure the client doesn’t try to re-use the connection. + add-header = Connection: close + # Set uid and gip to a appropriate user on your server. In many + # installations ``zun`` will be correct. + uid = zun + gid = zun + +Then start the uwsgi server:: + + uwsgi ./zun-uwsgi.ini + +Or start in background with:: + + uwsgi -d ./zun-uwsgi.ini diff --git a/setup.cfg b/setup.cfg index b20f0dec1..a8fa22768 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,6 +51,8 @@ console_scripts = zun-compute = zun.cmd.compute:main zun-db-manage = zun.cmd.db_manage:main zun-wsproxy = zun.cmd.wsproxy:main +wsgi_scripts = + zun-api-wsgi = zun.api.wsgi:init_application oslo.config.opts = zun = zun.opts:list_opts diff --git a/zun/api/app.wsgi b/zun/api/app.wsgi index 6f263f0ed..fe2caa23e 100644 --- a/zun/api/app.wsgi +++ b/zun/api/app.wsgi @@ -14,24 +14,6 @@ See https://pecan.readthedocs.org/en/latest/deployment.html for details. """ -import sys +from zun.api import wsgi -from oslo_log import log - -from zun.api import app -from zun.common import profiler -from zun.common import service -import zun.conf - - -CONF = zun.conf.CONF -LOG = log.getLogger(__name__) - -# Initialize the oslo configuration library and logging -service.prepare_service(sys.argv) -profiler.setup('zun-api', CONF.host) - -LOG.debug("Configuration:") -CONF.log_opt_values(LOG, log.DEBUG) - -application = app.load_app() +application = wsgi.init_application(argv=[]) diff --git a/zun/api/wsgi.py b/zun/api/wsgi.py new file mode 100644 index 000000000..2e5be9d8c --- /dev/null +++ b/zun/api/wsgi.py @@ -0,0 +1,35 @@ +# 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. + +import sys + +from oslo_log import log + +from zun.api import app +from zun.common import profiler +from zun.common import service +import zun.conf + + +CONF = zun.conf.CONF +LOG = log.getLogger(__name__) + + +def init_application(): + # Initialize the oslo configuration library and logging + service.prepare_service(sys.argv) + profiler.setup('zun-api', CONF.host) + + LOG.debug("Configuration:") + CONF.log_opt_values(LOG, log.DEBUG) + + return app.load_app() diff --git a/zun/tests/contrib/gate_hook.sh b/zun/tests/contrib/gate_hook.sh index fe03f452a..273c4f383 100755 --- a/zun/tests/contrib/gate_hook.sh +++ b/zun/tests/contrib/gate_hook.sh @@ -23,7 +23,7 @@ db=$2 export DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin kuryr-libnetwork https://git.openstack.org/openstack/kuryr-libnetwork" export DEVSTACK_LOCAL_CONFIG+=$'\n'"enable_plugin devstack-plugin-container https://git.openstack.org/openstack/devstack-plugin-container" -export DEVSTACK_LOCAL_CONFIG+=$'\n'"ZUN_USE_MOD_WSGI=True" +export DEVSTACK_LOCAL_CONFIG+=$'\n'"ZUN_USE_UWSGI=True" if [ "$driver" = "docker" ]; then export DEVSTACK_LOCAL_CONFIG+=$'\n'"ZUN_DRIVER=docker"