Merge "Migration logic for neutron policy-in-code"
diff --git a/.zuul.yaml b/.zuul.yaml
index 7ac30d8..645843c 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -19,6 +19,16 @@
           - controller
 
 - nodeset:
+    name: openstack-single-node-xenial
+    nodes:
+      - name: controller
+        label: ubuntu-xenial
+    groups:
+      - name: tempest
+        nodes:
+          - controller
+
+- nodeset:
     name: devstack-single-node-centos-7
     nodes:
       - name: controller
@@ -78,6 +88,66 @@
         nodes:
           - compute1
 
+- nodeset:
+    name: openstack-two-node-bionic
+    nodes:
+      - name: controller
+        label: ubuntu-bionic
+      - name: compute1
+        label: ubuntu-bionic
+    groups:
+      # Node where tests are executed and test results collected
+      - name: tempest
+        nodes:
+          - controller
+      # Nodes running the compute service
+      - name: compute
+        nodes:
+          - controller
+          - compute1
+      # Nodes that are not the controller
+      - name: subnode
+        nodes:
+          - compute1
+      # Switch node for multinode networking setup
+      - name: switch
+        nodes:
+          - controller
+      # Peer nodes for multinode networking setup
+      - name: peers
+        nodes:
+          - compute1
+
+- nodeset:
+    name: openstack-two-node-xenial
+    nodes:
+      - name: controller
+        label: ubuntu-xenial
+      - name: compute1
+        label: ubuntu-xenial
+    groups:
+      # Node where tests are executed and test results collected
+      - name: tempest
+        nodes:
+          - controller
+      # Nodes running the compute service
+      - name: compute
+        nodes:
+          - controller
+          - compute1
+      # Nodes that are not the controller
+      - name: subnode
+        nodes:
+          - compute1
+      # Switch node for multinode networking setup
+      - name: switch
+        nodes:
+          - controller
+      # Peer nodes for multinode networking setup
+      - name: peers
+        nodes:
+          - compute1
+
 - job:
     name: devstack-base
     parent: multinode
@@ -199,7 +269,7 @@
     description: |
       Minimal devstack base job, intended for use by jobs that need
       less than the normal minimum set of required-projects.
-    nodeset: openstack-single-node
+    nodeset: openstack-single-node-bionic
     required-projects:
       - git.openstack.org/openstack/requirements
     vars:
@@ -241,8 +311,8 @@
       This base job can be used for single node and multinode devstack jobs.
 
       With a single node nodeset, this job sets up an "all-in-one" (aio)
-      devstack with the six OpenStack services included in the devstack tree:
-      keystone, glance, cinder, neutron, nova and swift.
+      devstack with the seven OpenStack services included in the devstack tree:
+      keystone, glance, cinder, neutron, nova, placement, and swift.
 
       With a two node nodeset, this job sets up an aio + compute node.
       The controller can be customised using host-vars.controller, the
@@ -258,13 +328,13 @@
 
       The run playbook consists of a single role, so it can be easily rewritten
       and extended.
-    nodeset: openstack-single-node
     required-projects:
       - git.openstack.org/openstack/cinder
       - git.openstack.org/openstack/glance
       - git.openstack.org/openstack/keystone
       - git.openstack.org/openstack/neutron
       - git.openstack.org/openstack/nova
+      - git.openstack.org/openstack/placement
       - git.openstack.org/openstack/swift
     timeout: 7200
     vars:
@@ -389,13 +459,30 @@
         USE_PYTHON3: true
 
 - job:
+    name: devstack-xenial
+    parent: devstack
+    nodeset: openstack-single-node-xenial
+    description: |
+      Simple singlenode test to verify functionality on devstack
+      side running on Xenial.
+
+- job:
     name: devstack-multinode
     parent: devstack
-    nodeset: openstack-two-node
+    nodeset: openstack-two-node-bionic
     description: |
       Simple multinode test to verify multinode functionality on devstack side.
       This is not meant to be used as a parent job.
 
+- job:
+    name: devstack-multinode-xenial
+    parent: devstack
+    nodeset: openstack-two-node-xenial
+    description: |
+      Simple multinode test to verify multinode functionality on devstack
+      side running on Xenial.
+      This is not meant to be used as a parent job.
+
 # NOTE(ianw) Platform tests have traditionally been non-voting because
 # we often have to rush things through devstack to stabilise the gate,
 # and these platforms don't have the round-the-clock support to avoid
@@ -422,6 +509,13 @@
     voting: false
 
 - job:
+    name: devstack-platform-xenial
+    parent: tempest-full
+    description: Ubuntu Xenial platform test
+    nodeset: openstack-single-node-xenial
+    voting: false
+
+- job:
     name: devstack-tox-base
     parent: devstack
     description: |
@@ -492,12 +586,15 @@
     check:
       jobs:
         - devstack
+        - devstack-xenial
         - devstack-ipv6:
             voting: false
         - devstack-platform-centos-7
         - devstack-platform-opensuse-150
         - devstack-platform-fedora-latest
+        - devstack-platform-xenial
         - devstack-multinode
+        - devstack-multinode-xenial
         - devstack-unit-tests
         - openstack-tox-bashate
         - ironic-tempest-dsvm-ipa-wholedisk-bios-agent_ipmitool-tinyipa:
@@ -527,6 +624,9 @@
     gate:
       jobs:
         - devstack
+        - devstack-xenial
+        - devstack-multinode
+        - devstack-multinode-xenial
         - devstack-unit-tests
         - openstack-tox-bashate
         - neutron-grenade-multinode:
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index b02061e..02d6911 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -172,12 +172,15 @@
 storlets                               `git://git.openstack.org/openstack/storlets <https://git.openstack.org/cgit/openstack/storlets>`__
 stx-config                             `git://git.openstack.org/openstack/stx-config <https://git.openstack.org/cgit/openstack/stx-config>`__
 stx-fault                              `git://git.openstack.org/openstack/stx-fault <https://git.openstack.org/cgit/openstack/stx-fault>`__
+stx-integ                              `git://git.openstack.org/openstack/stx-integ <https://git.openstack.org/cgit/openstack/stx-integ>`__
+stx-nfv                                `git://git.openstack.org/openstack/stx-nfv <https://git.openstack.org/cgit/openstack/stx-nfv>`__
 stx-update                             `git://git.openstack.org/openstack/stx-update <https://git.openstack.org/cgit/openstack/stx-update>`__
 tacker                                 `git://git.openstack.org/openstack/tacker <https://git.openstack.org/cgit/openstack/tacker>`__
 tap-as-a-service                       `git://git.openstack.org/openstack/tap-as-a-service <https://git.openstack.org/cgit/openstack/tap-as-a-service>`__
 tap-as-a-service-dashboard             `git://git.openstack.org/openstack/tap-as-a-service-dashboard <https://git.openstack.org/cgit/openstack/tap-as-a-service-dashboard>`__
 tatu                                   `git://git.openstack.org/openstack/tatu <https://git.openstack.org/cgit/openstack/tatu>`__
 telemetry-tempest-plugin               `git://git.openstack.org/openstack/telemetry-tempest-plugin <https://git.openstack.org/cgit/openstack/telemetry-tempest-plugin>`__
+tobiko                                 `git://git.openstack.org/openstack/tobiko <https://git.openstack.org/cgit/openstack/tobiko>`__
 tricircle                              `git://git.openstack.org/openstack/tricircle <https://git.openstack.org/cgit/openstack/tricircle>`__
 trio2o                                 `git://git.openstack.org/openstack/trio2o <https://git.openstack.org/cgit/openstack/trio2o>`__
 trove                                  `git://git.openstack.org/openstack/trove <https://git.openstack.org/cgit/openstack/trove>`__
diff --git a/inc/python b/inc/python
index d8b8169..5fb7245 100644
--- a/inc/python
+++ b/inc/python
@@ -490,17 +490,6 @@
     _setup_package_with_constraints_edit $project_dir -e $extras
 }
 
-# determine if a project as specified by directory is in
-# projects.txt. This will not be an exact match because we throw away
-# the namespacing when we clone, but it should be good enough in all
-# practical ways.
-function is_in_projects_txt {
-    local project_dir=$1
-    local project_name
-    project_name=$(basename $project_dir)
-    grep -q "/$project_name\$" $REQUIREMENTS_DIR/projects.txt
-}
-
 # ``pip install -e`` the package, which processes the dependencies
 # using pip before running `setup.py develop`
 #
diff --git a/lib/placement b/lib/placement
index a1602ba..da69e39 100644
--- a/lib/placement
+++ b/lib/placement
@@ -3,9 +3,6 @@
 # lib/placement
 # Functions to control the configuration and operation of the **Placement** service
 #
-# Currently the placement service is embedded in nova. Eventually we
-# expect this to change so this file is started as a separate entity
-# despite making use of some *NOVA* variables and files.
 
 # Dependencies:
 #
@@ -29,23 +26,21 @@
 # Defaults
 # --------
 
-PLACEMENT_CONF_DIR=/etc/nova
-PLACEMENT_CONF=$PLACEMENT_CONF_DIR/nova.conf
-PLACEMENT_AUTH_STRATEGY=${PLACEMENT_AUTH_STRATEGY:-placement}
-# Nova virtual environment
+PLACEMENT_DIR=$DEST/placement
+PLACEMENT_CONF_DIR=/etc/placement
+PLACEMENT_CONF=$PLACEMENT_CONF_DIR/placement.conf
+PLACEMENT_AUTH_CACHE_DIR=${PLACEMENT_AUTH_CACHE_DIR:-/var/cache/placement}
+PLACEMENT_AUTH_STRATEGY=${PLACEMENT_AUTH_STRATEGY:-keystone}
+# Placement virtual environment
 if [[ ${USE_VENV} = True ]]; then
-    PROJECT_VENV["nova"]=${NOVA_DIR}.venv
-    PLACEMENT_BIN_DIR=${PROJECT_VENV["nova"]}/bin
+    PROJECT_VENV["placement"]=${PLACEMENT_DIR}.venv
+    PLACEMENT_BIN_DIR=${PROJECT_VENV["placement"]}/bin
 else
     PLACEMENT_BIN_DIR=$(get_python_exec_prefix)
 fi
-PLACEMENT_UWSGI=$PLACEMENT_BIN_DIR/nova-placement-api
+PLACEMENT_UWSGI=$PLACEMENT_BIN_DIR/placement-api
 PLACEMENT_UWSGI_CONF=$PLACEMENT_CONF_DIR/placement-uwsgi.ini
 
-# The placement service can optionally use a separate database
-# connection. Set PLACEMENT_DB_ENABLED to True to use it.
-PLACEMENT_DB_ENABLED=$(trueorfalse False PLACEMENT_DB_ENABLED)
-
 if is_service_enabled tls-proxy; then
     PLACEMENT_SERVICE_PROTOCOL="https"
 fi
@@ -67,30 +62,28 @@
 # cleanup_placement() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_placement {
-    sudo rm -f $(apache_site_config_for nova-placement-api)
     sudo rm -f $(apache_site_config_for placement-api)
     remove_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI"
+    sudo rm -f $PLACEMENT_AUTH_CACHE_DIR/*
 }
 
 # _config_placement_apache_wsgi() - Set WSGI config files
 function _config_placement_apache_wsgi {
     local placement_api_apache_conf
     local venv_path=""
-    local nova_bin_dir=""
-    nova_bin_dir=$(get_python_exec_prefix)
+    local placement_bin_dir=""
+    placement_bin_dir=$(get_python_exec_prefix)
     placement_api_apache_conf=$(apache_site_config_for placement-api)
 
-    # reuse nova's venv if there is one as placement code lives
-    # there
     if [[ ${USE_VENV} = True ]]; then
-        venv_path="python-path=${PROJECT_VENV["nova"]}/lib/$(python_version)/site-packages"
-        nova_bin_dir=${PROJECT_VENV["nova"]}/bin
+        venv_path="python-path=${PROJECT_VENV["placement"]}/lib/$(python_version)/site-packages"
+        placement_bin_dir=${PROJECT_VENV["placement"]}/bin
     fi
 
     sudo cp $FILES/apache-placement-api.template $placement_api_apache_conf
     sudo sed -e "
         s|%APACHE_NAME%|$APACHE_NAME|g;
-        s|%PUBLICWSGI%|$nova_bin_dir/nova-placement-api|g;
+        s|%PUBLICWSGI%|$placement_bin_dir/placement-api|g;
         s|%SSLENGINE%|$placement_ssl|g;
         s|%SSLCERTFILE%|$placement_certfile|g;
         s|%SSLKEYFILE%|$placement_keyfile|g;
@@ -110,19 +103,23 @@
     iniset $conf placement user_domain_name "$SERVICE_DOMAIN_NAME"
     iniset $conf placement project_name "$SERVICE_TENANT_NAME"
     iniset $conf placement project_domain_name "$SERVICE_DOMAIN_NAME"
-    # TODO(cdent): auth_strategy, which is common to see in these
-    # blocks is not currently used here. For the time being the
-    # placement api uses the auth_strategy configuration setting
-    # established by the nova api. This avoids, for the time, being,
-    # creating redundant configuration items that are just used for
-    # testing.
+    iniset $conf placement auth_strategy $PLACEMENT_AUTH_STRATEGY
+}
+
+# create_placement_conf() - Write config
+function create_placement_conf {
+    rm -f $PLACEMENT_CONF
+    iniset $PLACEMENT_CONF placement_database connection `database_connection_url placement`
+    iniset $PLACEMENT_CONF DEFAULT debug "$ENABLE_DEBUG_LOG_LEVEL"
+    iniset $PLACEMENT_CONF api auth_strategy $PLACEMENT_AUTH_STRATEGY
+    configure_auth_token_middleware $PLACEMENT_CONF placement $PLACEMENT_AUTH_CACHE_DIR
+    setup_logging $PLACEMENT_CONF
 }
 
 # configure_placement() - Set config files, create data dirs, etc
 function configure_placement {
-    if [ "$PLACEMENT_DB_ENABLED" != False ]; then
-        iniset $PLACEMENT_CONF placement_database connection `database_connection_url placement`
-    fi
+    sudo install -d -o $STACK_USER $PLACEMENT_CONF_DIR
+    create_placement_conf
 
     if [[ "$WSGI_MODE" == "uwsgi" ]]; then
         write_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI" "/placement"
@@ -143,25 +140,28 @@
         "$placement_api_url"
 }
 
+# create_placement_cache_dir() - Create directories for keystone cache
+function create_placement_cache_dir {
+    # Create cache dir
+    sudo install -d -o $STACK_USER $PLACEMENT_AUTH_CACHE_DIR
+    rm -f $PLACEMENT_AUTH_CACHE_DIR/*
+}
+
 # init_placement() - Create service user and endpoints
-# If PLACEMENT_DB_ENABLED is true, create the separate placement db
-# using, for now, the api_db migrations.
 function init_placement {
-    if [ "$PLACEMENT_DB_ENABLED" != False ]; then
-        recreate_database placement
-        # Database migration will be handled when nova does an api_db sync
-        # TODO(cdent): When placement is extracted we'll do our own sync
-        # here.
-    fi
+    recreate_database placement
+    $PLACEMENT_BIN_DIR/placement-manage db sync
     create_placement_accounts
+    create_placement_cache_dir
 }
 
 # install_placement() - Collect source and prepare
 function install_placement {
     install_apache_wsgi
     # Install the openstackclient placement client plugin for CLI
-    # TODO(mriedem): Use pip_install_gr once osc-placement is in g-r.
-    pip_install osc-placement
+    pip_install_gr osc-placement
+    git_clone $PLACEMENT_REPO $PLACEMENT_DIR $PLACEMENT_BRANCH
+    setup_develop $PLACEMENT_DIR
 }
 
 # start_placement_api() - Start the API processes ahead of other things
diff --git a/lib/tls b/lib/tls
index 217f40e..0032449 100644
--- a/lib/tls
+++ b/lib/tls
@@ -547,6 +547,9 @@
     LimitRequestFieldSize $f_header_size
     RequestHeader set X-Forwarded-Proto "https"
 
+    # Avoid races (at the cost of performance) to re-use a pooled connection
+    # where the connection is closed (bug 1807518).
+    SetEnv proxy-initial-not-pooled
     <Location />
         ProxyPass http://$b_host:$b_port/ retry=0 nocanon
         ProxyPassReverse http://$b_host:$b_port/
diff --git a/roles/setup-devstack-source-dirs/README.rst b/roles/setup-devstack-source-dirs/README.rst
index 4ebf839..49d22c3 100644
--- a/roles/setup-devstack-source-dirs/README.rst
+++ b/roles/setup-devstack-source-dirs/README.rst
@@ -9,3 +9,8 @@
    :default: /opt/stack
 
    The devstack base directory.
+
+ .. zuul:rolevar:: devstack_sources_branch
+    :default: None
+
+    The target branch to be setup (where available).
diff --git a/roles/setup-devstack-source-dirs/tasks/main.yaml b/roles/setup-devstack-source-dirs/tasks/main.yaml
index e6bbae2..c196c37 100644
--- a/roles/setup-devstack-source-dirs/tasks/main.yaml
+++ b/roles/setup-devstack-source-dirs/tasks/main.yaml
@@ -12,6 +12,35 @@
   with_items: '{{ found_repos.files }}'
   become: yes
 
+- name: Setup refspec for repos into devstack working directory
+  shell:
+    # Copied almost "as-is" from devstack-gate setup-workspace function
+    # but removing the dependency on functions.sh
+    # TODO this should be rewritten as a python module.
+    cmd: |
+      cd {{ devstack_base_dir }}/{{ item.path | basename }}
+      base_branch={{ devstack_sources_branch }}
+      if git branch -a | grep "$base_branch" > /dev/null ; then
+          git checkout $base_branch
+      elif [[ "$base_branch" == stable/* ]]; then
+          # Look for an eol tag for the stable branch.
+          eol_tag=${base_branch#stable/}-eol
+          if git tag -l |grep $eol_tag >/dev/null; then
+              git checkout $eol_tag
+              git reset --hard $eol_tag
+              if ! git clean -x -f -d -q ; then
+                  sleep 1
+                  git clean -x -f -d -q
+              fi
+          fi
+      else
+          git checkout master
+      fi
+  args:
+    executable: /bin/bash
+  with_items: '{{ found_repos.files }}'
+  when: devstack_sources_branch is defined
+
 - name: Set ownership of repos
   file:
     path: '{{ devstack_base_dir }}'
diff --git a/setup.cfg b/setup.cfg
index fcd2b13..825d386 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,7 +4,7 @@
 description-file =
     README.rst
 author = OpenStack
-author-email = openstack-dev@lists.openstack.org
+author-email = openstack-discuss@lists.openstack.org
 home-page = https://docs.openstack.org/devstack/latest
 classifier =
     Intended Audience :: Developers
diff --git a/stack.sh b/stack.sh
index be3c4be..144c233 100755
--- a/stack.sh
+++ b/stack.sh
@@ -335,6 +335,13 @@
     # no-op on other platforms.
     sudo yum-config-manager --enable rhel-7-server-optional-rpms
 
+    # Enable the Software Collections (SCL) repository for CentOS.
+    # This repository includes useful software (e.g. the Go Toolset)
+    # which is not present in the main repository.
+    if [[ "$os_VENDOR" =~ (CentOS) ]]; then
+        yum_install centos-release-scl
+    fi
+
     if is_oraclelinux; then
         sudo yum-config-manager --enable ol7_optional_latest ol7_addons ol7_MySQL56
     fi
@@ -894,8 +901,6 @@
     stack_install_service neutron
 fi
 
-# Nova configuration is used by placement so we need to create nova.conf
-# first.
 if is_service_enabled nova; then
     # Compute service
     stack_install_service nova
diff --git a/stackrc b/stackrc
index 34bd677..170d3b6 100644
--- a/stackrc
+++ b/stackrc
@@ -298,6 +298,10 @@
 SWIFT_REPO=${SWIFT_REPO:-${GIT_BASE}/openstack/swift.git}
 SWIFT_BRANCH=${SWIFT_BRANCH:-$TARGET_BRANCH}
 
+# placement service
+PLACEMENT_REPO=${PLACEMENT_REPO:-${GIT_BASE}/openstack/placement.git}
+PLACEMENT_BRANCH=${PLACEMENT_BRANCH:-$TARGET_BRANCH}
+
 ##############
 #
 #  Testing Components
@@ -763,7 +767,7 @@
 fi
 ETCD_PORT=${ETCD_PORT:-2379}
 ETCD_PEER_PORT=${ETCD_PEER_PORT:-2380}
-ETCD_DOWNLOAD_URL=${ETCD_DOWNLOAD_URL:-https://github.com/coreos/etcd/releases/download}
+ETCD_DOWNLOAD_URL=${ETCD_DOWNLOAD_URL:-https://github.com/etcd-io/etcd/releases/download}
 ETCD_NAME=etcd-$ETCD_VERSION-linux-$ETCD_ARCH
 ETCD_DOWNLOAD_FILE=$ETCD_NAME.tar.gz
 ETCD_DOWNLOAD_LOCATION=$ETCD_DOWNLOAD_URL/$ETCD_VERSION/$ETCD_DOWNLOAD_FILE