Browse code

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

Kevin Benton authored on 2017/06/13 16:31:01
Showing 4 changed files
... ...
@@ -511,6 +511,16 @@
511 511
     #    changes to devstack w/o gating on it for all devstack changes.
512 512
     # * nova-next: maintained by nova for unreleased/undefaulted
513 513
     #    things like cellsv2 and placement-api
514
+    # * neutron-fullstack-with-uwsgi: maintained by neutron for fullstack test
515
+    #    when neutron-api is served by uwsgi, it's in exprimental for testing.
516
+    #    the next cycle we can remove this  job if things turn out to be
517
+    #    stable enough.
518
+    # * neutron-functional-with-uwsgi: maintained by neutron for functional
519
+    #    test. Next cycle we can remove this one if things turn out to be
520
+    #    stable engouh with uwsgi.
521
+    # * neutron-tempest-with-uwsgi: maintained by neutron for tempest test.
522
+    #    Next cycle we can remove this if everything run out stable enough.
523
+
514 524
     experimental:
515 525
       jobs:
516 526
         - nova-cells-v1:
... ...
@@ -518,3 +528,6 @@
518 518
               - ^.*\.rst$
519 519
               - ^doc/.*$
520 520
         - nova-next
521
+        - neutron-fullstack-with-uwsgi
522
+        - neutron-functional-with-uwsgi
523
+        - neutron-tempest-with-uwsgi
521 524
\ No newline at end of file
522 525
new file mode 100644
... ...
@@ -0,0 +1,36 @@
0
+Listen %PUBLICPORT%
1
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D(us)" neutron_combined
2
+
3
+<Directory %NEUTRON_BIN%>
4
+    Require all granted
5
+</Directory>
6
+
7
+<VirtualHost *:%PUBLICPORT%>
8
+    WSGIDaemonProcess neutron-server processes=%APIWORKERS% threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
9
+    WSGIProcessGroup neutron-server
10
+    WSGIScriptAlias / %NEUTRON_BIN%/neutron-api
11
+    WSGIApplicationGroup %{GLOBAL}
12
+    WSGIPassAuthorization On
13
+    ErrorLogFormat "%M"
14
+    ErrorLog /var/log/%APACHE_NAME%/neutron.log
15
+    CustomLog /var/log/%APACHE_NAME%/neutron_access.log neutron_combined
16
+    %SSLENGINE%
17
+    %SSLCERTFILE%
18
+    %SSLKEYFILE%
19
+</VirtualHost>
20
+
21
+
22
+%SSLLISTEN%<VirtualHost *:443>
23
+%SSLLISTEN%    %SSLENGINE%
24
+%SSLLISTEN%    %SSLCERTFILE%
25
+%SSLLISTEN%    %SSLKEYFILE%
26
+%SSLLISTEN%</VirtualHost>
27
+
28
+Alias /networking %NEUTRON_BIN%/neutron-api
29
+<Location /networking>
30
+    SetHandler wsgi-script
31
+    Options +ExecCGI
32
+    WSGIProcessGroup neutron-server
33
+    WSGIApplicationGroup %{GLOBAL}
34
+    WSGIPassAuthorization On
35
+</Location>
... ...
@@ -28,6 +28,12 @@ set +o xtrace
28 28
 # Set up default directories
29 29
 GITDIR["python-neutronclient"]=$DEST/python-neutronclient
30 30
 
31
+# NEUTRON_DEPLOY_MOD_WSGI defines how neutron is deployed, allowed values:
32
+# - False (default) : Run neutron under Eventlet
33
+# - True : Run neutron under uwsgi
34
+# TODO(annp): Switching to uwsgi in next cycle if things turn out to be stable
35
+# enough
36
+NEUTRON_DEPLOY_MOD_WSGI=${NEUTRON_DEPLOY_MOD_WSGI:-False}
31 37
 NEUTRON_AGENT=${NEUTRON_AGENT:-openvswitch}
32 38
 NEUTRON_DIR=$DEST/neutron
33 39
 NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
... ...
@@ -58,6 +64,8 @@ NEUTRON_CREATE_INITIAL_NETWORKS=${NEUTRON_CREATE_INITIAL_NETWORKS:-True}
58 58
 NEUTRON_STATE_PATH=${NEUTRON_STATE_PATH:=$DATA_DIR/neutron}
59 59
 NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
60 60
 
61
+NEUTRON_UWSGI_CONF=$NEUTRON_CONF_DIR/neutron-api-uwsgi.ini
62
+
61 63
 # By default, use the ML2 plugin
62 64
 NEUTRON_CORE_PLUGIN=${NEUTRON_CORE_PLUGIN:-ml2}
63 65
 NEUTRON_CORE_PLUGIN_CONF_FILENAME=${NEUTRON_CORE_PLUGIN_CONF_FILENAME:-ml2_conf.ini}
... ...
@@ -286,7 +294,7 @@ function configure_neutron_new {
286 286
     # Format logging
287 287
     setup_logging $NEUTRON_CONF
288 288
 
289
-    if is_service_enabled tls-proxy; then
289
+    if is_service_enabled tls-proxy && [ "$NEUTRON_DEPLOY_MOD_WSGI" == "False" ]; then
290 290
         # Set the service port for a proxy to take the original
291 291
         iniset $NEUTRON_CONF DEFAULT bind_port "$NEUTRON_SERVICE_PORT_INT"
292 292
         iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True
... ...
@@ -357,6 +365,15 @@ function configure_neutron_nova_new {
357 357
 
358 358
 # create_neutron_accounts() - Create required service accounts
359 359
 function create_neutron_accounts_new {
360
+    local neutron_url
361
+
362
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
363
+        neutron_url=$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST/networking/
364
+    else
365
+        neutron_url=$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/
366
+    fi
367
+
368
+
360 369
     if [[ "$ENABLED_SERVICES" =~ "neutron-api" ]]; then
361 370
 
362 371
         create_service_user "neutron"
... ...
@@ -364,8 +381,7 @@ function create_neutron_accounts_new {
364 364
         neutron_service=$(get_or_create_service "neutron" \
365 365
             "network" "Neutron Service")
366 366
         get_or_create_endpoint $neutron_service \
367
-            "$REGION_NAME" \
368
-            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/"
367
+            "$REGION_NAME" "$neutron_url"
369 368
     fi
370 369
 }
371 370
 
... ...
@@ -427,6 +443,7 @@ function install_neutronclient {
427 427
 function start_neutron_api {
428 428
     local service_port=$NEUTRON_SERVICE_PORT
429 429
     local service_protocol=$NEUTRON_SERVICE_PROTOCOL
430
+    local neutron_url
430 431
     if is_service_enabled tls-proxy; then
431 432
         service_port=$NEUTRON_SERVICE_PORT_INT
432 433
         service_protocol="http"
... ...
@@ -440,17 +457,24 @@ function start_neutron_api {
440 440
         opts+=" --config-file $cfg_file"
441 441
     done
442 442
 
443
-    # Start the Neutron service
444
-    # TODO(sc68cal) Stop hard coding this
445
-    run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $opts"
446
-
447
-    if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$NEUTRON_SERVICE_HOST:$service_port; then
448
-        die $LINENO "neutron-api did not start"
443
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
444
+        run_process neutron-api "$NEUTRON_BIN_DIR/uwsgi --procname-prefix neutron-api --ini $NEUTRON_UWSGI_CONF"
445
+        neutron_url=$service_protocol://$NEUTRON_SERVICE_HOST/networking/
446
+        enable_service neutron-rpc-server
447
+        run_process neutron-rpc-server "$NEUTRON_BIN_DIR/neutron-rpc-server $opts"
448
+    else
449
+        # Start the Neutron service
450
+        # TODO(sc68cal) Stop hard coding this
451
+        run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $opts"
452
+        neutron_url=$service_protocol://$NEUTRON_SERVICE_HOST:$service_port
453
+        # Start proxy if enabled
454
+        if is_service_enabled tls-proxy; then
455
+            start_tls_proxy neutron '*' $NEUTRON_SERVICE_PORT $NEUTRON_SERVICE_HOST $NEUTRON_SERVICE_PORT_INT
456
+        fi
449 457
     fi
450 458
 
451
-    # Start proxy if enabled
452
-    if is_service_enabled tls-proxy; then
453
-        start_tls_proxy neutron '*' $NEUTRON_SERVICE_PORT $NEUTRON_SERVICE_HOST $NEUTRON_SERVICE_PORT_INT
459
+    if ! wait_for_service $SERVICE_TIMEOUT $neutron_url; then
460
+        die $LINENO "neutron-api did not start"
454 461
     fi
455 462
 }
456 463
 
... ...
@@ -497,6 +521,10 @@ function stop_neutron_new {
497 497
         stop_process $serv
498 498
     done
499 499
 
500
+    if is_service_enabled neutron-rpc-server; then
501
+        stop_process neutron-rpc-server
502
+    fi
503
+
500 504
     if is_service_enabled neutron-dhcp; then
501 505
         stop_process neutron-dhcp
502 506
         pid=$(ps aux | awk '/[d]nsmasq.+interface=(tap|ns-)/ { print $2 }')
... ...
@@ -551,6 +579,13 @@ function neutron_deploy_rootwrap_filters_new {
551 551
 # neutron-legacy is removed.
552 552
 # TODO(sc68cal) Remove when neutron-legacy is no more.
553 553
 function cleanup_neutron {
554
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
555
+        stop_process neutron-api
556
+        stop_process neutron-rpc-server
557
+        remove_uwsgi_config "$NEUTRON_UWSGI_CONF" "$NEUTRON_BIN_DIR/neutron-api"
558
+        sudo rm -f $(apache_site_config_for neutron-api)
559
+    fi
560
+
554 561
     if is_neutron_legacy_enabled; then
555 562
         # Call back to old function
556 563
         cleanup_mutnauq "$@"
... ...
@@ -566,6 +601,10 @@ function configure_neutron {
566 566
     else
567 567
         configure_neutron_new "$@"
568 568
     fi
569
+
570
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
571
+        write_uwsgi_config "$NEUTRON_UWSGI_CONF" "$NEUTRON_BIN_DIR/neutron-api" "/networking"
572
+    fi
569 573
 }
570 574
 
571 575
 function configure_neutron_nova {
... ...
@@ -86,6 +86,15 @@ NEUTRON_CONF_DIR=/etc/neutron
86 86
 NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
87 87
 export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"}
88 88
 
89
+# NEUTRON_DEPLOY_MOD_WSGI defines how neutron is deployed, allowed values:
90
+# - False (default) : Run neutron under Eventlet
91
+# - True : Run neutron under uwsgi
92
+# TODO(annp): Switching to uwsgi in next cycle if things turn out to be stable
93
+# enough
94
+NEUTRON_DEPLOY_MOD_WSGI=${NEUTRON_DEPLOY_MOD_WSGI:-False}
95
+
96
+NEUTRON_UWSGI_CONF=$NEUTRON_CONF_DIR/neutron-api-uwsgi.ini
97
+
89 98
 # Agent binaries.  Note, binary paths for other agents are set in per-service
90 99
 # scripts in lib/neutron_plugins/services/
91 100
 AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent"
... ...
@@ -402,6 +411,13 @@ function create_nova_conf_neutron {
402 402
 
403 403
 # Migrated from keystone_data.sh
404 404
 function create_mutnauq_accounts {
405
+    local neutron_url
406
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
407
+        neutron_url=$Q_PROTOCOL://$SERVICE_HOST/networking/
408
+    else
409
+        neutron_url=$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/
410
+    fi
411
+
405 412
     if [[ "$ENABLED_SERVICES" =~ "q-svc" ]]; then
406 413
 
407 414
         create_service_user "neutron"
... ...
@@ -409,8 +425,7 @@ function create_mutnauq_accounts {
409 409
         get_or_create_service "neutron" "network" "Neutron Service"
410 410
         get_or_create_endpoint \
411 411
             "network" \
412
-            "$REGION_NAME" \
413
-            "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/"
412
+            "$REGION_NAME" "$neutron_url"
414 413
     fi
415 414
 }
416 415
 
... ...
@@ -460,6 +475,7 @@ function start_neutron_service_and_check {
460 460
     local service_port=$Q_PORT
461 461
     local service_protocol=$Q_PROTOCOL
462 462
     local cfg_file_options
463
+    local neutron_url
463 464
 
464 465
     cfg_file_options="$(determine_config_files neutron-server)"
465 466
 
... ...
@@ -468,16 +484,24 @@ function start_neutron_service_and_check {
468 468
         service_protocol="http"
469 469
     fi
470 470
     # Start the Neutron service
471
-    run_process q-svc "$NEUTRON_BIN_DIR/neutron-server $cfg_file_options"
471
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
472
+        enable_service neutron-api
473
+        run_process neutron-api "$NEUTRON_BIN_DIR/uwsgi --procname-prefix neutron-api --ini $NEUTRON_UWSGI_CONF"
474
+        neutron_url=$Q_PROTOCOL://$Q_HOST/networking/
475
+        enable_service neutron-rpc-server
476
+        run_process neutron-rpc-server "$NEUTRON_BIN_DIR/neutron-rpc-server $cfg_file_options"
477
+    else
478
+        run_process q-svc "$NEUTRON_BIN_DIR/neutron-server $cfg_file_options"
479
+        neutron_url=$service_protocol://$Q_HOST:$service_port
480
+        # Start proxy if enabled
481
+        if is_service_enabled tls-proxy; then
482
+            start_tls_proxy neutron '*' $Q_PORT $Q_HOST $Q_PORT_INT
483
+        fi
484
+    fi
472 485
     echo "Waiting for Neutron to start..."
473 486
 
474
-    local testcmd="wget ${ssl_ca} --no-proxy -q -O- $service_protocol://$Q_HOST:$service_port"
487
+    local testcmd="wget ${ssl_ca} --no-proxy -q -O- $neutron_url"
475 488
     test_with_retry "$testcmd" "Neutron did not start" $SERVICE_TIMEOUT
476
-
477
-    # Start proxy if enabled
478
-    if is_service_enabled tls-proxy; then
479
-        start_tls_proxy neutron '*' $Q_PORT $Q_HOST $Q_PORT_INT
480
-    fi
481 489
 }
482 490
 
483 491
 # Control of the l2 agent is separated out to make it easier to test partial
... ...
@@ -532,7 +556,12 @@ function stop_mutnauq_other {
532 532
         [ ! -z "$pid" ] && sudo kill -9 $pid
533 533
     fi
534 534
 
535
-    stop_process q-svc
535
+    if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
536
+        stop_process neutron-rpc-server
537
+        stop_process neutron-api
538
+    else
539
+        stop_process q-svc
540
+    fi
536 541
 
537 542
     if is_service_enabled q-l3; then
538 543
         sudo pkill -f "radvd -C $DATA_DIR/neutron/ra"
... ...
@@ -715,7 +744,7 @@ function _configure_neutron_common {
715 715
     # Format logging
716 716
     setup_logging $NEUTRON_CONF
717 717
 
718
-    if is_service_enabled tls-proxy; then
718
+    if is_service_enabled tls-proxy && [ "$NEUTRON_DEPLOY_MOD_WSGI" == "False" ]; then
719 719
         # Set the service port for a proxy to take the original
720 720
         iniset $NEUTRON_CONF DEFAULT bind_port "$Q_PORT_INT"
721 721
         iniset $NEUTRON_CONF oslo_middleware enable_proxy_headers_parsing True