WSGI Neutron integration

This patch provides a new mechanism to deploy Neutron using
WSGI script. This also starts a Neutron RPC server process
when the Neutron API is loaded via a WSGI entry point to
serve the agents.

Co-Authored-By: Victor Morales <victor.morales@intel.com>
Co-Authored-By: Nguyen Phuong An <AnNP@vn.fujitsu.com>

Change-Id: I16a199b04858bfc03ef50d9883154dba8b0d66ea
Depends-On: https://review.openstack.org/#/c/580049/
Partially-implements: blueprint run-in-wsgi-server
This commit is contained in:
Kevin Benton 2017-06-13 00:31:01 -07:00 committed by Nguyen Phuong An
parent 3b5477d635
commit 66b361b538
4 changed files with 140 additions and 23 deletions

View File

@ -511,6 +511,16 @@
# changes to devstack w/o gating on it for all devstack changes. # changes to devstack w/o gating on it for all devstack changes.
# * nova-next: maintained by nova for unreleased/undefaulted # * nova-next: maintained by nova for unreleased/undefaulted
# things like cellsv2 and placement-api # things like cellsv2 and placement-api
# * neutron-fullstack-with-uwsgi: maintained by neutron for fullstack test
# when neutron-api is served by uwsgi, it's in exprimental for testing.
# the next cycle we can remove this job if things turn out to be
# stable enough.
# * neutron-functional-with-uwsgi: maintained by neutron for functional
# test. Next cycle we can remove this one if things turn out to be
# stable engouh with uwsgi.
# * neutron-tempest-with-uwsgi: maintained by neutron for tempest test.
# Next cycle we can remove this if everything run out stable enough.
experimental: experimental:
jobs: jobs:
- nova-cells-v1: - nova-cells-v1:
@ -518,3 +528,6 @@
- ^.*\.rst$ - ^.*\.rst$
- ^doc/.*$ - ^doc/.*$
- nova-next - nova-next
- neutron-fullstack-with-uwsgi
- neutron-functional-with-uwsgi
- neutron-tempest-with-uwsgi

View File

@ -0,0 +1,36 @@
Listen %PUBLICPORT%
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D(us)" neutron_combined
<Directory %NEUTRON_BIN%>
Require all granted
</Directory>
<VirtualHost *:%PUBLICPORT%>
WSGIDaemonProcess neutron-server processes=%APIWORKERS% threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
WSGIProcessGroup neutron-server
WSGIScriptAlias / %NEUTRON_BIN%/neutron-api
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
ErrorLogFormat "%M"
ErrorLog /var/log/%APACHE_NAME%/neutron.log
CustomLog /var/log/%APACHE_NAME%/neutron_access.log neutron_combined
%SSLENGINE%
%SSLCERTFILE%
%SSLKEYFILE%
</VirtualHost>
%SSLLISTEN%<VirtualHost *:443>
%SSLLISTEN% %SSLENGINE%
%SSLLISTEN% %SSLCERTFILE%
%SSLLISTEN% %SSLKEYFILE%
%SSLLISTEN%</VirtualHost>
Alias /networking %NEUTRON_BIN%/neutron-api
<Location /networking>
SetHandler wsgi-script
Options +ExecCGI
WSGIProcessGroup neutron-server
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
</Location>

View File

@ -28,6 +28,12 @@ set +o xtrace
# Set up default directories # Set up default directories
GITDIR["python-neutronclient"]=$DEST/python-neutronclient GITDIR["python-neutronclient"]=$DEST/python-neutronclient
# NEUTRON_DEPLOY_MOD_WSGI defines how neutron is deployed, allowed values:
# - False (default) : Run neutron under Eventlet
# - True : Run neutron under uwsgi
# TODO(annp): Switching to uwsgi in next cycle if things turn out to be stable
# enough
NEUTRON_DEPLOY_MOD_WSGI=${NEUTRON_DEPLOY_MOD_WSGI:-False}
NEUTRON_AGENT=${NEUTRON_AGENT:-openvswitch} NEUTRON_AGENT=${NEUTRON_AGENT:-openvswitch}
NEUTRON_DIR=$DEST/neutron NEUTRON_DIR=$DEST/neutron
NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron} NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
@ -58,6 +64,8 @@ NEUTRON_CREATE_INITIAL_NETWORKS=${NEUTRON_CREATE_INITIAL_NETWORKS:-True}
NEUTRON_STATE_PATH=${NEUTRON_STATE_PATH:=$DATA_DIR/neutron} NEUTRON_STATE_PATH=${NEUTRON_STATE_PATH:=$DATA_DIR/neutron}
NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron} NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
NEUTRON_UWSGI_CONF=$NEUTRON_CONF_DIR/neutron-api-uwsgi.ini
# By default, use the ML2 plugin # By default, use the ML2 plugin
NEUTRON_CORE_PLUGIN=${NEUTRON_CORE_PLUGIN:-ml2} NEUTRON_CORE_PLUGIN=${NEUTRON_CORE_PLUGIN:-ml2}
NEUTRON_CORE_PLUGIN_CONF_FILENAME=${NEUTRON_CORE_PLUGIN_CONF_FILENAME:-ml2_conf.ini} NEUTRON_CORE_PLUGIN_CONF_FILENAME=${NEUTRON_CORE_PLUGIN_CONF_FILENAME:-ml2_conf.ini}
@ -286,7 +294,7 @@ function configure_neutron_new {
# Format logging # Format logging
setup_logging $NEUTRON_CONF setup_logging $NEUTRON_CONF
if is_service_enabled tls-proxy; then if is_service_enabled tls-proxy && [ "$NEUTRON_DEPLOY_MOD_WSGI" == "False" ]; then
# Set the service port for a proxy to take the original # Set the service port for a proxy to take the original
iniset $NEUTRON_CONF DEFAULT bind_port "$NEUTRON_SERVICE_PORT_INT" iniset $NEUTRON_CONF DEFAULT bind_port "$NEUTRON_SERVICE_PORT_INT"
iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True
@ -357,6 +365,15 @@ function configure_neutron_nova_new {
# create_neutron_accounts() - Create required service accounts # create_neutron_accounts() - Create required service accounts
function create_neutron_accounts_new { function create_neutron_accounts_new {
local neutron_url
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
neutron_url=$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST/networking/
else
neutron_url=$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/
fi
if [[ "$ENABLED_SERVICES" =~ "neutron-api" ]]; then if [[ "$ENABLED_SERVICES" =~ "neutron-api" ]]; then
create_service_user "neutron" create_service_user "neutron"
@ -364,8 +381,7 @@ function create_neutron_accounts_new {
neutron_service=$(get_or_create_service "neutron" \ neutron_service=$(get_or_create_service "neutron" \
"network" "Neutron Service") "network" "Neutron Service")
get_or_create_endpoint $neutron_service \ get_or_create_endpoint $neutron_service \
"$REGION_NAME" \ "$REGION_NAME" "$neutron_url"
"$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/"
fi fi
} }
@ -427,6 +443,7 @@ function install_neutronclient {
function start_neutron_api { function start_neutron_api {
local service_port=$NEUTRON_SERVICE_PORT local service_port=$NEUTRON_SERVICE_PORT
local service_protocol=$NEUTRON_SERVICE_PROTOCOL local service_protocol=$NEUTRON_SERVICE_PROTOCOL
local neutron_url
if is_service_enabled tls-proxy; then if is_service_enabled tls-proxy; then
service_port=$NEUTRON_SERVICE_PORT_INT service_port=$NEUTRON_SERVICE_PORT_INT
service_protocol="http" service_protocol="http"
@ -440,18 +457,25 @@ function start_neutron_api {
opts+=" --config-file $cfg_file" opts+=" --config-file $cfg_file"
done done
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
run_process neutron-api "$NEUTRON_BIN_DIR/uwsgi --procname-prefix neutron-api --ini $NEUTRON_UWSGI_CONF"
neutron_url=$service_protocol://$NEUTRON_SERVICE_HOST/networking/
enable_service neutron-rpc-server
run_process neutron-rpc-server "$NEUTRON_BIN_DIR/neutron-rpc-server $opts"
else
# Start the Neutron service # Start the Neutron service
# TODO(sc68cal) Stop hard coding this # TODO(sc68cal) Stop hard coding this
run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $opts" run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $opts"
neutron_url=$service_protocol://$NEUTRON_SERVICE_HOST:$service_port
if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$NEUTRON_SERVICE_HOST:$service_port; then
die $LINENO "neutron-api did not start"
fi
# Start proxy if enabled # Start proxy if enabled
if is_service_enabled tls-proxy; then if is_service_enabled tls-proxy; then
start_tls_proxy neutron '*' $NEUTRON_SERVICE_PORT $NEUTRON_SERVICE_HOST $NEUTRON_SERVICE_PORT_INT start_tls_proxy neutron '*' $NEUTRON_SERVICE_PORT $NEUTRON_SERVICE_HOST $NEUTRON_SERVICE_PORT_INT
fi fi
fi
if ! wait_for_service $SERVICE_TIMEOUT $neutron_url; then
die $LINENO "neutron-api did not start"
fi
} }
# start_neutron() - Start running processes # start_neutron() - Start running processes
@ -497,6 +521,10 @@ function stop_neutron_new {
stop_process $serv stop_process $serv
done done
if is_service_enabled neutron-rpc-server; then
stop_process neutron-rpc-server
fi
if is_service_enabled neutron-dhcp; then if is_service_enabled neutron-dhcp; then
stop_process neutron-dhcp stop_process neutron-dhcp
pid=$(ps aux | awk '/[d]nsmasq.+interface=(tap|ns-)/ { print $2 }') pid=$(ps aux | awk '/[d]nsmasq.+interface=(tap|ns-)/ { print $2 }')
@ -551,6 +579,13 @@ function neutron_deploy_rootwrap_filters_new {
# neutron-legacy is removed. # neutron-legacy is removed.
# TODO(sc68cal) Remove when neutron-legacy is no more. # TODO(sc68cal) Remove when neutron-legacy is no more.
function cleanup_neutron { function cleanup_neutron {
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
stop_process neutron-api
stop_process neutron-rpc-server
remove_uwsgi_config "$NEUTRON_UWSGI_CONF" "$NEUTRON_BIN_DIR/neutron-api"
sudo rm -f $(apache_site_config_for neutron-api)
fi
if is_neutron_legacy_enabled; then if is_neutron_legacy_enabled; then
# Call back to old function # Call back to old function
cleanup_mutnauq "$@" cleanup_mutnauq "$@"
@ -566,6 +601,10 @@ function configure_neutron {
else else
configure_neutron_new "$@" configure_neutron_new "$@"
fi fi
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
write_uwsgi_config "$NEUTRON_UWSGI_CONF" "$NEUTRON_BIN_DIR/neutron-api" "/networking"
fi
} }
function configure_neutron_nova { function configure_neutron_nova {

View File

@ -86,6 +86,15 @@ NEUTRON_CONF_DIR=/etc/neutron
NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"} export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"}
# NEUTRON_DEPLOY_MOD_WSGI defines how neutron is deployed, allowed values:
# - False (default) : Run neutron under Eventlet
# - True : Run neutron under uwsgi
# TODO(annp): Switching to uwsgi in next cycle if things turn out to be stable
# enough
NEUTRON_DEPLOY_MOD_WSGI=${NEUTRON_DEPLOY_MOD_WSGI:-False}
NEUTRON_UWSGI_CONF=$NEUTRON_CONF_DIR/neutron-api-uwsgi.ini
# Agent binaries. Note, binary paths for other agents are set in per-service # Agent binaries. Note, binary paths for other agents are set in per-service
# scripts in lib/neutron_plugins/services/ # scripts in lib/neutron_plugins/services/
AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent" AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent"
@ -402,6 +411,13 @@ function create_nova_conf_neutron {
# Migrated from keystone_data.sh # Migrated from keystone_data.sh
function create_mutnauq_accounts { function create_mutnauq_accounts {
local neutron_url
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
neutron_url=$Q_PROTOCOL://$SERVICE_HOST/networking/
else
neutron_url=$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/
fi
if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
create_service_user "neutron" create_service_user "neutron"
@ -409,8 +425,7 @@ function create_mutnauq_accounts {
get_or_create_service "neutron" "network" "Neutron Service" get_or_create_service "neutron" "network" "Neutron Service"
get_or_create_endpoint \ get_or_create_endpoint \
"network" \ "network" \
"$REGION_NAME" \ "$REGION_NAME" "$neutron_url"
"$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/"
fi fi
} }
@ -460,6 +475,7 @@ function start_neutron_service_and_check {
local service_port=$Q_PORT local service_port=$Q_PORT
local service_protocol=$Q_PROTOCOL local service_protocol=$Q_PROTOCOL
local cfg_file_options local cfg_file_options
local neutron_url
cfg_file_options="$(determine_config_files neutron-server)" cfg_file_options="$(determine_config_files neutron-server)"
@ -468,16 +484,24 @@ function start_neutron_service_and_check {
service_protocol="http" service_protocol="http"
fi fi
# Start the Neutron service # Start the Neutron service
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
enable_service neutron-api
run_process neutron-api "$NEUTRON_BIN_DIR/uwsgi --procname-prefix neutron-api --ini $NEUTRON_UWSGI_CONF"
neutron_url=$Q_PROTOCOL://$Q_HOST/networking/
enable_service neutron-rpc-server
run_process neutron-rpc-server "$NEUTRON_BIN_DIR/neutron-rpc-server $cfg_file_options"
else
run_process q-svc "$NEUTRON_BIN_DIR/neutron-server $cfg_file_options" run_process q-svc "$NEUTRON_BIN_DIR/neutron-server $cfg_file_options"
echo "Waiting for Neutron to start..." neutron_url=$service_protocol://$Q_HOST:$service_port
local testcmd="wget ${ssl_ca} --no-proxy -q -O- $service_protocol://$Q_HOST:$service_port"
test_with_retry "$testcmd" "Neutron did not start" $SERVICE_TIMEOUT
# Start proxy if enabled # Start proxy if enabled
if is_service_enabled tls-proxy; then if is_service_enabled tls-proxy; then
start_tls_proxy neutron '*' $Q_PORT $Q_HOST $Q_PORT_INT start_tls_proxy neutron '*' $Q_PORT $Q_HOST $Q_PORT_INT
fi fi
fi
echo "Waiting for Neutron to start..."
local testcmd="wget ${ssl_ca} --no-proxy -q -O- $neutron_url"
test_with_retry "$testcmd" "Neutron did not start" $SERVICE_TIMEOUT
} }
# Control of the l2 agent is separated out to make it easier to test partial # Control of the l2 agent is separated out to make it easier to test partial
@ -532,7 +556,12 @@ function stop_mutnauq_other {
[ ! -z "$pid" ] && sudo kill -9 $pid [ ! -z "$pid" ] && sudo kill -9 $pid
fi fi
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
stop_process neutron-rpc-server
stop_process neutron-api
else
stop_process q-svc stop_process q-svc
fi
if is_service_enabled q-l3; then if is_service_enabled q-l3; then
sudo pkill -f "radvd -C $DATA_DIR/neutron/ra" sudo pkill -f "radvd -C $DATA_DIR/neutron/ra"
@ -715,7 +744,7 @@ function _configure_neutron_common {
# Format logging # Format logging
setup_logging $NEUTRON_CONF setup_logging $NEUTRON_CONF
if is_service_enabled tls-proxy; then if is_service_enabled tls-proxy && [ "$NEUTRON_DEPLOY_MOD_WSGI" == "False" ]; then
# Set the service port for a proxy to take the original # Set the service port for a proxy to take the original
iniset $NEUTRON_CONF DEFAULT bind_port "$Q_PORT_INT" iniset $NEUTRON_CONF DEFAULT bind_port "$Q_PORT_INT"
iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True