Merge "lib/neutron: Use NEUTRON_PLUGIN instead of hardcoding ml2"
diff --git a/data/devstack-plugins-registry.header b/data/devstack-plugins-registry.header
index 6119ab5..576dbbd 100644
--- a/data/devstack-plugins-registry.header
+++ b/data/devstack-plugins-registry.header
@@ -1,18 +1,16 @@
-..
+.. Note to patch submitters:
 
-  Note to patch submitters:
+   # ============================= #
+   # THIS FILE IS AUTOGENERATED !  #
+   # ============================= #
 
-  # ============================= #
-  # THIS FILE IS AUTOGENERATED !  #
-  # ============================= #
+   ** Plugins are found automatically and added to this list **
 
-  ** Plugins are found automatically and added to this list **
+   This file is created by a periodic proposal job.  You should not
+   edit this file.
 
-  This file is created by a periodic proposal job.  You should not
-  edit this file.
-
-  You should edit the files data/devstack-plugins-registry.footer
-  data/devstack-plugins-registry.header to modify this text.
+   You should edit the files data/devstack-plugins-registry.footer
+   data/devstack-plugins-registry.header to modify this text.
 
 ==========================
  DevStack Plugin Registry
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index c5b1634..b26fd1e 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -76,12 +76,6 @@
         RABBIT_PASSWORD=secret
         SERVICE_PASSWORD=secret
 
-        # Do not use Nova-Network
-        disable_service n-net
-        # Enable Neutron
-        ENABLED_SERVICES+=,q-svc,q-dhcp,q-meta,q-agt,q-l3
-
-
         ## Neutron options
         Q_USE_SECGROUP=True
         FLOATING_RANGE="172.18.161.0/24"
@@ -389,11 +383,7 @@
 
         Q_USE_PROVIDER_NETWORKING=True
 
-        # Do not use Nova-Network
-        disable_service n-net
-
-        # Neutron
-        ENABLED_SERVICES+=,q-svc,q-dhcp,q-meta,q-agt
+        disable_service q-l3
 
         ## Neutron Networking options used to create Neutron Subnets
 
@@ -530,12 +520,6 @@
     RABBIT_PASSWORD=secret
     SERVICE_PASSWORD=secret
 
-    # Do not use Nova-Network
-    disable_service n-net
-    # Enable Neutron
-    ENABLED_SERVICES+=,q-svc,q-dhcp,q-meta,q-agt,q-l3
-
-
     ## Neutron options
     Q_USE_SECGROUP=True
     FLOATING_RANGE="172.18.161.0/24"
@@ -582,10 +566,7 @@
     Q_ML2_PLUGIN_MECHANISM_DRIVERS=macvtap
     Q_USE_PROVIDER_NETWORKING=True
 
-    #Enable Neutron services
-    disable_service n-net
     enable_plugin neutron git://git.openstack.org/openstack/neutron
-    ENABLED_SERVICES+=,q-agt,q-svc
 
     ## MacVTap agent options
     Q_AGENT=macvtap
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index bb85270..9d023bf 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -1,18 +1,16 @@
-..
+.. Note to patch submitters:
 
-  Note to patch submitters:
+   # ============================= #
+   # THIS FILE IS AUTOGENERATED !  #
+   # ============================= #
 
-  # ============================= #
-  # THIS FILE IS AUTOGENERATED !  #
-  # ============================= #
+   ** Plugins are found automatically and added to this list **
 
-  ** Plugins are found automatically and added to this list **
+   This file is created by a periodic proposal job.  You should not
+   edit this file.
 
-  This file is created by a periodic proposal job.  You should not
-  edit this file.
-
-  You should edit the files data/devstack-plugins-registry.footer
-  data/devstack-plugins-registry.header to modify this text.
+   You should edit the files data/devstack-plugins-registry.footer
+   data/devstack-plugins-registry.header to modify this text.
 
 ==========================
  DevStack Plugin Registry
@@ -26,6 +24,7 @@
 ====================================== ===
 Plugin Name                            URL
 ====================================== ===
+almanach                               `git://git.openstack.org/openstack/almanach <https://git.openstack.org/cgit/openstack/almanach>`__
 aodh                                   `git://git.openstack.org/openstack/aodh <https://git.openstack.org/cgit/openstack/aodh>`__
 app-catalog-ui                         `git://git.openstack.org/openstack/app-catalog-ui <https://git.openstack.org/cgit/openstack/app-catalog-ui>`__
 astara                                 `git://git.openstack.org/openstack/astara <https://git.openstack.org/cgit/openstack/astara>`__
@@ -63,11 +62,12 @@
 gnocchi                                `git://git.openstack.org/openstack/gnocchi <https://git.openstack.org/cgit/openstack/gnocchi>`__
 group-based-policy                     `git://git.openstack.org/openstack/group-based-policy <https://git.openstack.org/cgit/openstack/group-based-policy>`__
 heat                                   `git://git.openstack.org/openstack/heat <https://git.openstack.org/cgit/openstack/heat>`__
-higgins                                `git://git.openstack.org/openstack/higgins <https://git.openstack.org/cgit/openstack/higgins>`__
 horizon-mellanox                       `git://git.openstack.org/openstack/horizon-mellanox <https://git.openstack.org/cgit/openstack/horizon-mellanox>`__
 ironic                                 `git://git.openstack.org/openstack/ironic <https://git.openstack.org/cgit/openstack/ironic>`__
 ironic-inspector                       `git://git.openstack.org/openstack/ironic-inspector <https://git.openstack.org/cgit/openstack/ironic-inspector>`__
 ironic-staging-drivers                 `git://git.openstack.org/openstack/ironic-staging-drivers <https://git.openstack.org/cgit/openstack/ironic-staging-drivers>`__
+karbor                                 `git://git.openstack.org/openstack/karbor <https://git.openstack.org/cgit/openstack/karbor>`__
+karbor-dashboard                       `git://git.openstack.org/openstack/karbor-dashboard <https://git.openstack.org/cgit/openstack/karbor-dashboard>`__
 kingbird                               `git://git.openstack.org/openstack/kingbird <https://git.openstack.org/cgit/openstack/kingbird>`__
 kuryr-libnetwork                       `git://git.openstack.org/openstack/kuryr-libnetwork <https://git.openstack.org/cgit/openstack/kuryr-libnetwork>`__
 magnum                                 `git://git.openstack.org/openstack/magnum <https://git.openstack.org/cgit/openstack/magnum>`__
@@ -103,6 +103,7 @@
 networking-plumgrid                    `git://git.openstack.org/openstack/networking-plumgrid <https://git.openstack.org/cgit/openstack/networking-plumgrid>`__
 networking-powervm                     `git://git.openstack.org/openstack/networking-powervm <https://git.openstack.org/cgit/openstack/networking-powervm>`__
 networking-sfc                         `git://git.openstack.org/openstack/networking-sfc <https://git.openstack.org/cgit/openstack/networking-sfc>`__
+networking-vpp                         `git://git.openstack.org/openstack/networking-vpp <https://git.openstack.org/cgit/openstack/networking-vpp>`__
 networking-vsphere                     `git://git.openstack.org/openstack/networking-vsphere <https://git.openstack.org/cgit/openstack/networking-vsphere>`__
 neutron                                `git://git.openstack.org/openstack/neutron <https://git.openstack.org/cgit/openstack/neutron>`__
 neutron-dynamic-routing                `git://git.openstack.org/openstack/neutron-dynamic-routing <https://git.openstack.org/cgit/openstack/neutron-dynamic-routing>`__
@@ -112,6 +113,7 @@
 neutron-vpnaas                         `git://git.openstack.org/openstack/neutron-vpnaas <https://git.openstack.org/cgit/openstack/neutron-vpnaas>`__
 nova-docker                            `git://git.openstack.org/openstack/nova-docker <https://git.openstack.org/cgit/openstack/nova-docker>`__
 nova-lxd                               `git://git.openstack.org/openstack/nova-lxd <https://git.openstack.org/cgit/openstack/nova-lxd>`__
+nova-mksproxy                          `git://git.openstack.org/openstack/nova-mksproxy <https://git.openstack.org/cgit/openstack/nova-mksproxy>`__
 nova-powervm                           `git://git.openstack.org/openstack/nova-powervm <https://git.openstack.org/cgit/openstack/nova-powervm>`__
 octavia                                `git://git.openstack.org/openstack/octavia <https://git.openstack.org/cgit/openstack/octavia>`__
 osprofiler                             `git://git.openstack.org/openstack/osprofiler <https://git.openstack.org/cgit/openstack/osprofiler>`__
@@ -124,12 +126,11 @@
 searchlight                            `git://git.openstack.org/openstack/searchlight <https://git.openstack.org/cgit/openstack/searchlight>`__
 searchlight-ui                         `git://git.openstack.org/openstack/searchlight-ui <https://git.openstack.org/cgit/openstack/searchlight-ui>`__
 senlin                                 `git://git.openstack.org/openstack/senlin <https://git.openstack.org/cgit/openstack/senlin>`__
-smaug                                  `git://git.openstack.org/openstack/smaug <https://git.openstack.org/cgit/openstack/smaug>`__
-smaug-dashboard                        `git://git.openstack.org/openstack/smaug-dashboard <https://git.openstack.org/cgit/openstack/smaug-dashboard>`__
 solum                                  `git://git.openstack.org/openstack/solum <https://git.openstack.org/cgit/openstack/solum>`__
 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>`__
 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>`__
 trove-dashboard                        `git://git.openstack.org/openstack/trove-dashboard <https://git.openstack.org/cgit/openstack/trove-dashboard>`__
 vitrage                                `git://git.openstack.org/openstack/vitrage <https://git.openstack.org/cgit/openstack/vitrage>`__
@@ -139,6 +140,8 @@
 watcher-dashboard                      `git://git.openstack.org/openstack/watcher-dashboard <https://git.openstack.org/cgit/openstack/watcher-dashboard>`__
 zaqar                                  `git://git.openstack.org/openstack/zaqar <https://git.openstack.org/cgit/openstack/zaqar>`__
 zaqar-ui                               `git://git.openstack.org/openstack/zaqar-ui <https://git.openstack.org/cgit/openstack/zaqar-ui>`__
+zun                                    `git://git.openstack.org/openstack/zun <https://git.openstack.org/cgit/openstack/zun>`__
+zun-ui                                 `git://git.openstack.org/openstack/zun-ui <https://git.openstack.org/cgit/openstack/zun-ui>`__
 ====================================== ===
 
 
diff --git a/extras.d/60-ceph.sh b/extras.d/60-ceph.sh
deleted file mode 100644
index cc90128..0000000
--- a/extras.d/60-ceph.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-# ceph.sh - DevStack extras script to install Ceph
-
-if is_service_enabled ceph; then
-    if [[ "$1" == "source" ]]; then
-        # Initial source
-        source $TOP_DIR/lib/ceph
-    elif [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
-        echo_summary "Installing Ceph"
-        check_os_support_ceph
-        if [ "$REMOTE_CEPH" = "False" ]; then
-            install_ceph
-            echo_summary "Configuring Ceph"
-            configure_ceph
-            # NOTE (leseb): Do everything here because we need to have Ceph started before the main
-            # OpenStack components. Ceph OSD must start here otherwise we can't upload any images.
-            echo_summary "Initializing Ceph"
-            init_ceph
-            start_ceph
-        else
-            install_ceph_remote
-        fi
-    elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
-        if is_service_enabled glance; then
-            echo_summary "Configuring Glance for Ceph"
-            configure_ceph_glance
-        fi
-        if is_service_enabled nova; then
-            echo_summary "Configuring Nova for Ceph"
-            configure_ceph_nova
-        fi
-        if is_service_enabled cinder; then
-            echo_summary "Configuring Cinder for Ceph"
-            configure_ceph_cinder
-        fi
-        if is_service_enabled n-cpu; then
-            # NOTE (leseb): the part below is a requirement to attach Ceph block devices
-            echo_summary "Configuring libvirt secret"
-            import_libvirt_secret_ceph
-        fi
-
-        if [ "$REMOTE_CEPH" = "False" ]; then
-            if is_service_enabled glance; then
-                echo_summary "Configuring Glance for Ceph"
-                configure_ceph_embedded_glance
-            fi
-            if is_service_enabled nova; then
-                echo_summary "Configuring Nova for Ceph"
-                configure_ceph_embedded_nova
-            fi
-            if is_service_enabled cinder; then
-                echo_summary "Configuring Cinder for Ceph"
-                configure_ceph_embedded_cinder
-            fi
-        fi
-    fi
-
-    if [[ "$1" == "unstack" ]]; then
-        if [ "$REMOTE_CEPH" = "True" ]; then
-            cleanup_ceph_remote
-        else
-            cleanup_ceph_embedded
-            stop_ceph
-        fi
-        cleanup_ceph_general
-    fi
-
-    if [[ "$1" == "clean" ]]; then
-        if [ "$REMOTE_CEPH" = "True" ]; then
-            cleanup_ceph_remote
-        else
-            cleanup_ceph_embedded
-        fi
-        cleanup_ceph_general
-    fi
-fi
diff --git a/files/debs/cinder b/files/debs/cinder
index 3595e01..c1b79fd 100644
--- a/files/debs/cinder
+++ b/files/debs/cinder
@@ -3,3 +3,4 @@
 open-iscsi-utils # Deprecated since quantal dist:precise
 qemu-utils
 tgt # NOPRIME
+thin-provisioning-tools
diff --git a/files/debs/tls-proxy b/files/debs/tls-proxy
index dce9c07..5bd8e21 100644
--- a/files/debs/tls-proxy
+++ b/files/debs/tls-proxy
@@ -1 +1 @@
-stud
+apache2
diff --git a/functions-common b/functions-common
index 3fdd71b..4716567 100644
--- a/functions-common
+++ b/functions-common
@@ -1686,7 +1686,7 @@
     local logfile=$2
 
     if [[ "$USE_SCREEN" = "True" ]]; then
-        screen_process "$name" "sudo tail -f $logfile"
+        screen_process "$name" "sudo tail -f $logfile | sed 's/\\\\\\\\x1b/\o033/g'"
     fi
 }
 
@@ -1880,7 +1880,7 @@
             # white listed elements in tree. We want these to move out
             # over time as well, but they are in tree, so we need to
             # manage that.
-            local exceptions="60-ceph.sh 80-tempest.sh"
+            local exceptions="80-tempest.sh"
             local extra
             extra=$(basename $extra_plugin_file_name)
             if [[ ! ( $exceptions =~ "$extra" ) ]]; then
@@ -2304,6 +2304,16 @@
     fi
 }
 
+# Service wrapper to stop services
+# reload_service service-name
+function reload_service {
+    if [ -x /bin/systemctl ]; then
+        sudo /bin/systemctl reload $1
+    else
+        sudo service $1 reload
+    fi
+}
+
 # Test with a finite retry loop.
 #
 function test_with_retry {
diff --git a/lib/apache b/lib/apache
index 2c84c7a..740f588 100644
--- a/lib/apache
+++ b/lib/apache
@@ -42,24 +42,40 @@
 
 # Functions
 # ---------
+
+# Enable apache mod and restart apache if it isn't already enabled.
+function enable_apache_mod {
+    local mod=$1
+    # Apache installation, because we mark it NOPRIME
+    if is_ubuntu || is_suse ; then
+        if ! a2query -m $mod ; then
+            sudo a2enmod $mod
+            restart_apache_server
+        fi
+    elif is_fedora; then
+        # pass
+        true
+    else
+        exit_distro_not_supported "apache enable mod"
+    fi
+}
+
 # install_apache_wsgi() - Install Apache server and wsgi module
 function install_apache_wsgi {
     # Apache installation, because we mark it NOPRIME
     if is_ubuntu; then
         # Install apache2, which is NOPRIME'd
         install_package apache2 libapache2-mod-wsgi
-        # WSGI isn't enabled by default, enable it
-        sudo a2enmod wsgi
     elif is_fedora; then
         sudo rm -f /etc/httpd/conf.d/000-*
         install_package httpd mod_wsgi
     elif is_suse; then
         install_package apache2 apache2-mod_wsgi
-        # WSGI isn't enabled by default, enable it
-        sudo a2enmod wsgi
     else
-        exit_distro_not_supported "apache installation"
+        exit_distro_not_supported "apache wsgi installation"
     fi
+    # WSGI isn't enabled by default, enable it
+    enable_apache_mod wsgi
 
     # ensure mod_version enabled for <IfVersion ...>.  This is
     # built-in statically on anything recent, but precise (2.2)
@@ -192,6 +208,11 @@
     time_stop "restart_apache_server"
 }
 
+# reload_apache_server
+function reload_apache_server {
+    reload_service $APACHE_NAME
+}
+
 # Restore xtrace
 $_XTRACE_LIB_APACHE
 
diff --git a/lib/ceph b/lib/ceph
deleted file mode 100644
index 1e55c48..0000000
--- a/lib/ceph
+++ /dev/null
@@ -1,381 +0,0 @@
-#!/bin/bash
-#
-# lib/ceph
-# Functions to control the configuration and operation of the **Ceph** storage service
-
-# Dependencies:
-#
-# - ``functions`` file
-# - ``CEPH_DATA_DIR`` or ``DATA_DIR`` must be defined
-
-# ``stack.sh`` calls the entry points in this order (via ``extras.d/60-ceph.sh``):
-#
-# - install_ceph
-# - configure_ceph
-# - init_ceph
-# - start_ceph
-# - stop_ceph
-# - cleanup_ceph
-
-# Save trace setting
-_XTRACE_LIB_CEPH=$(set +o | grep xtrace)
-set +o xtrace
-
-
-# Defaults
-# --------
-
-# Set ``CEPH_DATA_DIR`` to the location of Ceph drives and objects.
-# Default is the common DevStack data directory.
-CEPH_DATA_DIR=${CEPH_DATA_DIR:-/var/lib/ceph}
-CEPH_DISK_IMAGE=${CEPH_DATA_DIR}/drives/images/ceph.img
-
-# Set ``CEPH_CONF_DIR`` to the location of the configuration files.
-# Default is ``/etc/ceph``.
-CEPH_CONF_DIR=${CEPH_CONF_DIR:-/etc/ceph}
-
-# DevStack will create a loop-back disk formatted as XFS to store the
-# Ceph data. Set ``CEPH_LOOPBACK_DISK_SIZE`` to the disk size in
-# kilobytes.
-# Default is 1 gigabyte.
-CEPH_LOOPBACK_DISK_SIZE_DEFAULT=4G
-CEPH_LOOPBACK_DISK_SIZE=${CEPH_LOOPBACK_DISK_SIZE:-$CEPH_LOOPBACK_DISK_SIZE_DEFAULT}
-
-# Common
-CEPH_FSID=$(uuidgen)
-CEPH_CONF_FILE=${CEPH_CONF_DIR}/ceph.conf
-
-# Glance
-GLANCE_CEPH_USER=${GLANCE_CEPH_USER:-glance}
-GLANCE_CEPH_POOL=${GLANCE_CEPH_POOL:-images}
-GLANCE_CEPH_POOL_PG=${GLANCE_CEPH_POOL_PG:-8}
-GLANCE_CEPH_POOL_PGP=${GLANCE_CEPH_POOL_PGP:-8}
-
-# Nova
-NOVA_CEPH_POOL=${NOVA_CEPH_POOL:-vms}
-NOVA_CEPH_POOL_PG=${NOVA_CEPH_POOL_PG:-8}
-NOVA_CEPH_POOL_PGP=${NOVA_CEPH_POOL_PGP:-8}
-
-# Cinder
-CINDER_CEPH_POOL=${CINDER_CEPH_POOL:-volumes}
-CINDER_CEPH_POOL_PG=${CINDER_CEPH_POOL_PG:-8}
-CINDER_CEPH_POOL_PGP=${CINDER_CEPH_POOL_PGP:-8}
-CINDER_CEPH_USER=${CINDER_CEPH_USER:-cinder}
-CINDER_CEPH_UUID=${CINDER_CEPH_UUID:-$(uuidgen)}
-
-# Set ``CEPH_REPLICAS`` to configure how many replicas are to be
-# configured for your Ceph cluster. By default we are configuring
-# only one replica since this is way less CPU and memory intensive. If
-# you are planning to test Ceph replication feel free to increase this value
-CEPH_REPLICAS=${CEPH_REPLICAS:-1}
-CEPH_REPLICAS_SEQ=$(seq ${CEPH_REPLICAS})
-
-# Connect to an existing Ceph cluster
-REMOTE_CEPH=$(trueorfalse False REMOTE_CEPH)
-REMOTE_CEPH_ADMIN_KEY_PATH=${REMOTE_CEPH_ADMIN_KEY_PATH:-$CEPH_CONF_DIR/ceph.client.admin.keyring}
-
-# Cinder encrypted volume tests are not supported with a Ceph backend due to
-# bug 1463525.
-ATTACH_ENCRYPTED_VOLUME_AVAILABLE=False
-
-
-# Functions
-# ------------
-
-function get_ceph_version {
-    local ceph_version_str
-    ceph_version_str=$(sudo ceph daemon mon.$(hostname) version | cut -d '"' -f 4 | cut -f 1,2 -d '.')
-    echo $ceph_version_str
-}
-
-# import_libvirt_secret_ceph() - Imports Cinder user key into libvirt
-# so it can connect to the Ceph cluster while attaching a Cinder block device
-function import_libvirt_secret_ceph {
-    cat > secret.xml <<EOF
-<secret ephemeral='no' private='no'>
-   <uuid>${CINDER_CEPH_UUID}</uuid>
-   <usage type='ceph'>
-     <name>client.${CINDER_CEPH_USER} secret</name>
-   </usage>
-</secret>
-EOF
-    sudo virsh secret-define --file secret.xml
-    sudo virsh secret-set-value --secret ${CINDER_CEPH_UUID} --base64 $(sudo ceph -c ${CEPH_CONF_FILE} auth get-key client.${CINDER_CEPH_USER})
-    sudo rm -f secret.xml
-}
-
-# undefine_virsh_secret() - Undefine Cinder key secret from libvirt
-function undefine_virsh_secret {
-    if is_service_enabled cinder || is_service_enabled nova; then
-        local virsh_uuid
-        virsh_uuid=$(sudo virsh secret-list | awk '/^ ?[0-9a-z]/ { print $1 }')
-        sudo virsh secret-undefine ${virsh_uuid} >/dev/null 2>&1
-    fi
-}
-
-
-# check_os_support_ceph() - Check if the operating system provides a decent version of Ceph
-function check_os_support_ceph {
-    if [[ ! ${DISTRO} =~ (trusty|f23|f24) ]]; then
-        echo "WARNING: your distro $DISTRO does not provide (at least) the Firefly release. Please use Ubuntu Trusty or Fedora 20 (and higher)"
-        if [[ "$FORCE_CEPH_INSTALL" != "yes" ]]; then
-            die $LINENO "If you wish to install Ceph on this distribution anyway run with FORCE_CEPH_INSTALL=yes"
-        fi
-        NO_UPDATE_REPOS=False
-    fi
-}
-
-# cleanup_ceph() - Remove residual data files, anything left over from previous
-# runs that a clean run would need to clean up
-function cleanup_ceph_remote {
-    # do a proper cleanup from here to avoid leftover on the remote Ceph cluster
-    if is_service_enabled glance; then
-        sudo ceph osd pool delete $GLANCE_CEPH_POOL $GLANCE_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
-        sudo ceph auth del client.$GLANCE_CEPH_USER > /dev/null 2>&1
-    fi
-    if is_service_enabled cinder; then
-        sudo ceph osd pool delete $CINDER_CEPH_POOL $CINDER_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
-        sudo ceph auth del client.$CINDER_CEPH_USER > /dev/null 2>&1
-    fi
-    if is_service_enabled c-bak; then
-        sudo ceph osd pool delete $CINDER_BAK_CEPH_POOL $CINDER_BAK_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
-        sudo ceph auth del client.$CINDER_BAK_CEPH_USER > /dev/null 2>&1
-    fi
-    if is_service_enabled nova; then
-        iniset $NOVA_CONF libvirt rbd_secret_uuid ""
-        sudo ceph osd pool delete $NOVA_CEPH_POOL $NOVA_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
-    fi
-}
-
-function cleanup_ceph_embedded {
-    sudo killall -w -9 ceph-mon
-    sudo killall -w -9 ceph-osd
-    sudo rm -rf ${CEPH_DATA_DIR}/*/*
-    if egrep -q ${CEPH_DATA_DIR} /proc/mounts; then
-        sudo umount ${CEPH_DATA_DIR}
-    fi
-    if [[ -e ${CEPH_DISK_IMAGE} ]]; then
-        sudo rm -f ${CEPH_DISK_IMAGE}
-    fi
-
-    # purge ceph config file and keys
-    sudo rm -rf ${CEPH_CONF_DIR}/*
-}
-
-function cleanup_ceph_general {
-    undefine_virsh_secret
-}
-
-
-# configure_ceph() - Set config files, create data dirs, etc
-function configure_ceph {
-    local count=0
-
-    # create a backing file disk
-    create_disk ${CEPH_DISK_IMAGE} ${CEPH_DATA_DIR} ${CEPH_LOOPBACK_DISK_SIZE}
-
-    # populate ceph directory
-    sudo mkdir -p ${CEPH_DATA_DIR}/{bootstrap-mds,bootstrap-osd,mds,mon,osd,tmp}
-
-    # create ceph monitor initial key and directory
-    sudo ceph-authtool /var/lib/ceph/tmp/keyring.mon.$(hostname) \
-        --create-keyring --name=mon. --add-key=$(ceph-authtool --gen-print-key) \
-        --cap mon 'allow *'
-    sudo mkdir /var/lib/ceph/mon/ceph-$(hostname)
-
-    # create a default ceph configuration file
-    sudo tee ${CEPH_CONF_FILE} > /dev/null <<EOF
-[global]
-fsid = ${CEPH_FSID}
-mon_initial_members = $(hostname)
-mon_host = ${SERVICE_HOST}
-auth_cluster_required = cephx
-auth_service_required = cephx
-auth_client_required = cephx
-filestore_xattr_use_omap = true
-osd crush chooseleaf type = 0
-osd journal size = 100
-EOF
-
-    # bootstrap the ceph monitor
-    sudo ceph-mon -c ${CEPH_CONF_FILE} --mkfs -i $(hostname) \
-        --keyring /var/lib/ceph/tmp/keyring.mon.$(hostname)
-
-    if is_ubuntu; then
-        sudo touch /var/lib/ceph/mon/ceph-$(hostname)/upstart
-        sudo initctl emit ceph-mon id=$(hostname)
-    else
-        sudo touch /var/lib/ceph/mon/ceph-$(hostname)/sysvinit
-        sudo service ceph start mon.$(hostname)
-    fi
-
-    # wait for the admin key to come up otherwise we will not be able to do the actions below
-    until [ -f ${CEPH_CONF_DIR}/ceph.client.admin.keyring ]; do
-        echo_summary "Waiting for the Ceph admin key to be ready..."
-
-        count=$(($count + 1))
-        if [ $count -eq 3 ]; then
-            die $LINENO "Maximum of 3 retries reached"
-        fi
-        sleep 5
-    done
-
-    # pools data and metadata were removed in the Giant release so depending on the version we apply different commands
-    local ceph_version
-    ceph_version=$(get_ceph_version)
-    # change pool replica size according to the CEPH_REPLICAS set by the user
-    if [[ ${ceph_version%%.*} -eq 0 ]] && [[ ${ceph_version##*.} -lt 87 ]]; then
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd size ${CEPH_REPLICAS}
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set data size ${CEPH_REPLICAS}
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set metadata size ${CEPH_REPLICAS}
-    else
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd size ${CEPH_REPLICAS}
-    fi
-
-    # create a simple rule to take OSDs instead of host with CRUSH
-    # then apply this rules to the default pool
-    if [[ $CEPH_REPLICAS -ne 1 ]]; then
-        sudo ceph -c ${CEPH_CONF_FILE} osd crush rule create-simple devstack default osd
-        RULE_ID=$(sudo ceph -c ${CEPH_CONF_FILE} osd crush rule dump devstack | awk '/rule_id/ {print $3}' | cut -d ',' -f1)
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd crush_ruleset ${RULE_ID}
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set data crush_ruleset ${RULE_ID}
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set metadata crush_ruleset ${RULE_ID}
-    fi
-
-    # create the OSD(s)
-    for rep in ${CEPH_REPLICAS_SEQ}; do
-        OSD_ID=$(sudo ceph -c ${CEPH_CONF_FILE} osd create)
-        sudo mkdir -p ${CEPH_DATA_DIR}/osd/ceph-${OSD_ID}
-        sudo ceph-osd -c ${CEPH_CONF_FILE} -i ${OSD_ID} --mkfs
-        sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create osd.${OSD_ID} \
-            mon 'allow profile osd ' osd 'allow *' | \
-            sudo tee ${CEPH_DATA_DIR}/osd/ceph-${OSD_ID}/keyring
-
-        # ceph's init script is parsing ${CEPH_DATA_DIR}/osd/ceph-${OSD_ID}/ and looking for a file
-        # 'upstart' or 'sysinitv', thanks to these 'touches' we are able to control OSDs daemons
-        # from the init script.
-        if is_ubuntu; then
-            sudo touch ${CEPH_DATA_DIR}/osd/ceph-${OSD_ID}/upstart
-        else
-            sudo touch ${CEPH_DATA_DIR}/osd/ceph-${OSD_ID}/sysvinit
-        fi
-    done
-}
-
-function configure_ceph_embedded_glance {
-    # configure Glance service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${GLANCE_CEPH_POOL} size ${CEPH_REPLICAS}
-    if [[ $CEPH_REPLICAS -ne 1 ]]; then
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${GLANCE_CEPH_POOL} crush_ruleset ${RULE_ID}
-    fi
-}
-
-# configure_ceph_glance() - Glance config needs to come after Glance is set up
-function configure_ceph_glance {
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${GLANCE_CEPH_POOL} ${GLANCE_CEPH_POOL_PG} ${GLANCE_CEPH_POOL_PGP}
-    sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${GLANCE_CEPH_USER} \
-        mon "allow r" \
-        osd "allow class-read object_prefix rbd_children, allow rwx pool=${GLANCE_CEPH_POOL}" | \
-        sudo tee ${CEPH_CONF_DIR}/ceph.client.${GLANCE_CEPH_USER}.keyring
-    sudo chown ${STACK_USER}:$(id -g -n $whoami) ${CEPH_CONF_DIR}/ceph.client.${GLANCE_CEPH_USER}.keyring
-
-    iniset $GLANCE_API_CONF DEFAULT show_image_direct_url True
-    iniset $GLANCE_API_CONF glance_store default_store rbd
-    iniset $GLANCE_API_CONF glance_store stores "file, http, rbd"
-    iniset $GLANCE_API_CONF glance_store rbd_store_ceph_conf $CEPH_CONF_FILE
-    iniset $GLANCE_API_CONF glance_store rbd_store_user $GLANCE_CEPH_USER
-    iniset $GLANCE_API_CONF glance_store rbd_store_pool $GLANCE_CEPH_POOL
-}
-
-function configure_ceph_embedded_nova {
-    # configure Nova service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${NOVA_CEPH_POOL} size ${CEPH_REPLICAS}
-    if [[ $CEPH_REPLICAS -ne 1 ]]; then
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${NOVA_CEPH_POOL} crush_ruleset ${RULE_ID}
-    fi
-}
-
-# configure_ceph_nova() - Nova config needs to come after Nova is set up
-function configure_ceph_nova {
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${NOVA_CEPH_POOL} ${NOVA_CEPH_POOL_PG} ${NOVA_CEPH_POOL_PGP}
-    iniset $NOVA_CONF libvirt rbd_user ${CINDER_CEPH_USER}
-    iniset $NOVA_CONF libvirt rbd_secret_uuid ${CINDER_CEPH_UUID}
-    iniset $NOVA_CONF libvirt inject_key false
-    iniset $NOVA_CONF libvirt disk_cachemodes "network=writeback"
-    iniset $NOVA_CONF libvirt images_type rbd
-    iniset $NOVA_CONF libvirt images_rbd_pool ${NOVA_CEPH_POOL}
-    iniset $NOVA_CONF libvirt images_rbd_ceph_conf ${CEPH_CONF_FILE}
-
-    if ! is_service_enabled cinder; then
-        sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_CEPH_USER} \
-            mon "allow r" \
-            osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_CEPH_POOL}, allow rwx pool=${NOVA_CEPH_POOL},allow rwx pool=${GLANCE_CEPH_POOL}" | \
-            sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring > /dev/null
-        sudo chown ${STACK_USER}:$(id -g -n $whoami) ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring
-    fi
-}
-
-function configure_ceph_embedded_cinder {
-    # Configure Cinder service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_CEPH_POOL} size ${CEPH_REPLICAS}
-    if [[ $CEPH_REPLICAS -ne 1 ]]; then
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_CEPH_POOL} crush_ruleset ${RULE_ID}
-    fi
-}
-
-# configure_ceph_cinder() - Cinder config needs to come after Cinder is set up
-function configure_ceph_cinder {
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${CINDER_CEPH_POOL} ${CINDER_CEPH_POOL_PG} ${CINDER_CEPH_POOL_PGP}
-    sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_CEPH_USER} \
-        mon "allow r" \
-        osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_CEPH_POOL}, allow rwx pool=${NOVA_CEPH_POOL},allow rwx pool=${GLANCE_CEPH_POOL}" | \
-        sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring
-    sudo chown ${STACK_USER}:$(id -g -n $whoami) ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring
-}
-
-# init_ceph() - Initialize databases, etc.
-function init_ceph {
-    # clean up from previous (possibly aborted) runs
-    # make sure to kill all ceph processes first
-    sudo pkill -f ceph-mon || true
-    sudo pkill -f ceph-osd || true
-}
-
-# install_ceph() - Collect source and prepare
-function install_ceph_remote {
-    install_package ceph-common
-}
-
-function install_ceph {
-    install_package ceph
-}
-
-# start_ceph() - Start running processes, including screen
-function start_ceph {
-    if is_ubuntu; then
-        sudo initctl emit ceph-mon id=$(hostname)
-        for id in $(sudo ceph -c ${CEPH_CONF_FILE} osd ls); do
-            sudo start ceph-osd id=${id}
-        done
-    else
-        sudo service ceph start
-    fi
-}
-
-# stop_ceph() - Stop running processes (non-screen)
-function stop_ceph {
-    if is_ubuntu; then
-        sudo service ceph-mon-all stop > /dev/null 2>&1
-        sudo service ceph-osd-all stop > /dev/null 2>&1
-    else
-        sudo service ceph stop > /dev/null 2>&1
-    fi
-}
-
-
-# Restore xtrace
-$_XTRACE_LIB_CEPH
-
-## Local variables:
-## mode: shell-script
-## End:
diff --git a/lib/cinder b/lib/cinder
index a87f395..0fe950b 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -305,8 +305,8 @@
     if is_service_enabled tls-proxy; then
         # Set the service port for a proxy to take the original
         iniset $CINDER_CONF DEFAULT osapi_volume_listen_port $CINDER_SERVICE_PORT_INT
-
         iniset $CINDER_CONF DEFAULT public_endpoint $CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT
+        iniset $CINDER_CONF DEFAULT osapi_volume_base_URL $CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT
     fi
 
     if [ "$SYSLOG" != "False" ]; then
@@ -534,7 +534,7 @@
 
     # Start proxies if enabled
     if is_service_enabled c-api && is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $CINDER_SERVICE_PORT $CINDER_SERVICE_HOST $CINDER_SERVICE_PORT_INT &
+        start_tls_proxy cinder '*' $CINDER_SERVICE_PORT $CINDER_SERVICE_HOST $CINDER_SERVICE_PORT_INT
     fi
 }
 
diff --git a/lib/glance b/lib/glance
index 8d95aad..a31e564 100644
--- a/lib/glance
+++ b/lib/glance
@@ -383,8 +383,8 @@
 function start_glance {
     local service_protocol=$GLANCE_SERVICE_PROTOCOL
     if is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $GLANCE_SERVICE_PORT $GLANCE_SERVICE_HOST $GLANCE_SERVICE_PORT_INT &
-        start_tls_proxy '*' $GLANCE_REGISTRY_PORT $GLANCE_SERVICE_HOST $GLANCE_REGISTRY_PORT_INT &
+        start_tls_proxy glance-service '*' $GLANCE_SERVICE_PORT $GLANCE_SERVICE_HOST $GLANCE_SERVICE_PORT_INT
+        start_tls_proxy glance-registry '*' $GLANCE_REGISTRY_PORT $GLANCE_SERVICE_HOST $GLANCE_REGISTRY_PORT_INT
     fi
 
     run_process g-reg "$GLANCE_BIN_DIR/glance-registry --config-file=$GLANCE_CONF_DIR/glance-registry.conf"
diff --git a/lib/keystone b/lib/keystone
index 6198e43..128b6dc 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -245,12 +245,9 @@
 
     # Enable caching
     iniset $KEYSTONE_CONF cache enabled "True"
-    iniset $KEYSTONE_CONF cache backend "oslo_cache.memcache_pool"
+    iniset $KEYSTONE_CONF cache backend "dogpile.cache.memcached"
     iniset $KEYSTONE_CONF cache memcache_servers localhost:11211
 
-    # Do not cache the catalog backend due to https://bugs.launchpad.net/keystone/+bug/1537617
-    iniset $KEYSTONE_CONF catalog caching "False"
-
     iniset_rpc_backend keystone $KEYSTONE_CONF
 
     # Register SSL certificates if provided
@@ -338,6 +335,8 @@
             iniset "$file" uwsgi buffer-size 65535
             # Make sure the client doesn't try to re-use the connection.
             iniset "$file" uwsgi add-header "Connection: close"
+            # This ensures that file descriptors aren't shared between processes.
+            iniset "$file" uwsgi lazy-apps true
         done
     fi
 
@@ -345,6 +344,8 @@
 
     iniset $KEYSTONE_CONF fernet_tokens key_repository "$KEYSTONE_CONF_DIR/fernet-keys/"
 
+    iniset $KEYSTONE_CONF credential key_repository "$KEYSTONE_CONF_DIR/credential-keys/"
+
     # Configure the project created by the 'keystone-manage bootstrap' as the cloud-admin project.
     # The users from this project are globally admin as before, but it also
     # allows policy changes in order to clarify the adminess scope.
@@ -514,6 +515,9 @@
         rm -rf "$KEYSTONE_CONF_DIR/fernet-keys/"
         $KEYSTONE_BIN_DIR/keystone-manage --config-file $KEYSTONE_CONF fernet_setup
     fi
+    rm -rf "$KEYSTONE_CONF_DIR/credential-keys/"
+    $KEYSTONE_BIN_DIR/keystone-manage --config-file $KEYSTONE_CONF credential_setup
+
 }
 
 # install_keystoneauth() - Collect source and prepare
@@ -609,8 +613,8 @@
 
     # Start proxies if enabled
     if is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $KEYSTONE_SERVICE_PORT $KEYSTONE_SERVICE_HOST $KEYSTONE_SERVICE_PORT_INT &
-        start_tls_proxy '*' $KEYSTONE_AUTH_PORT $KEYSTONE_AUTH_HOST $KEYSTONE_AUTH_PORT_INT &
+        start_tls_proxy keystone-service '*' $KEYSTONE_SERVICE_PORT $KEYSTONE_SERVICE_HOST $KEYSTONE_SERVICE_PORT_INT
+        start_tls_proxy keystone-auth '*' $KEYSTONE_AUTH_PORT $KEYSTONE_AUTH_HOST $KEYSTONE_AUTH_PORT_INT
     fi
 
     # (re)start memcached to make sure we have a clean memcache.
diff --git a/lib/lvm b/lib/lvm
index b9d7c39..d35a76f 100644
--- a/lib/lvm
+++ b/lib/lvm
@@ -58,7 +58,9 @@
     if [[ -n "$backing_file" ]] && [[ -e "$backing_file" ]]; then
         local vg_dev
         vg_dev=$(sudo losetup -j $backing_file | awk -F':' '/'$BACKING_FILE_SUFFIX'/ { print $1}')
-        sudo losetup -d $vg_dev
+        if [[ -n "$vg_dev" ]]; then
+            sudo losetup -d $vg_dev
+        fi
         rm -f $backing_file
     fi
 }
diff --git a/lib/neutron b/lib/neutron
index 3fbcbd9..ab84f7e 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -126,7 +126,7 @@
     iniset $NEUTRON_CONF oslo_concurrency lock_path $NEUTRON_STATE_PATH/lock
     iniset $NEUTRON_CONF DEFAULT use_syslog $SYSLOG
 
-    iniset $NEUTRON_CONF DEFAULT debug True
+    iniset $NEUTRON_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
 
     iniset_rpc_backend neutron $NEUTRON_CONF
 
@@ -172,7 +172,7 @@
     # Neutron OVS or LB agent
     if is_service_enabled neutron-agent; then
         iniset $NEUTRON_PLUGIN_CONF agent tunnel_types vxlan
-        iniset $NEUTRON_PLUGIN_CONF DEFAULT debug True
+        iniset $NEUTRON_PLUGIN_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
 
         # Configure the neutron agent
         if [[ $NEUTRON_AGENT == "linuxbridge" ]]; then
@@ -188,7 +188,7 @@
     if is_service_enabled neutron-dhcp; then
         cp $NEUTRON_DIR/etc/dhcp_agent.ini.sample $NEUTRON_DHCP_CONF
 
-        iniset $NEUTRON_DHCP_CONF DEFAULT debug True
+        iniset $NEUTRON_DHCP_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
         # make it so we have working DNS from guests
         iniset $NEUTRON_DHCP_CONF DEFAULT dnsmasq_local_resolv True
 
@@ -202,7 +202,7 @@
         iniset $NEUTRON_L3_CONF DEFAULT interface_driver $NEUTRON_AGENT
         iniset $NEUTRON_CONF DEFAULT service_plugins router
         iniset $NEUTRON_L3_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
-        iniset $NEUTRON_L3_CONF DEFAULT debug True
+        iniset $NEUTRON_L3_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
         neutron_plugin_configure_l3_agent $NEUTRON_L3_CONF
     fi
 
@@ -210,7 +210,7 @@
     if is_service_enabled neutron-metadata-agent; then
         cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $NEUTRON_META_CONF
 
-        iniset $NEUTRON_META_CONF DEFAULT debug True
+        iniset $NEUTRON_META_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
         iniset $NEUTRON_META_CONF DEFAULT nova_metadata_ip $SERVICE_HOST
         iniset $NEUTRON_META_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
 
@@ -305,6 +305,9 @@
 
     iniset $NOVA_CONF DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
 
+    # optionally set options in nova_conf
+    neutron_plugin_create_nova_conf
+
     if is_service_enabled neutron-metadata-agent; then
         iniset $NOVA_CONF neutron service_metadata_proxy "True"
     fi
@@ -409,7 +412,7 @@
 
     # Start proxy if enabled
     if is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $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
 }
 
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index b1b5230..123ba42 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -211,13 +211,15 @@
 # Example: ``OVS_PHYSICAL_BRIDGE=br-eth1``
 OVS_PHYSICAL_BRIDGE=${OVS_PHYSICAL_BRIDGE:-br-ex}
 
+default_route_dev=$(ip route | grep ^default | awk '{print $5}')
+die_if_not_set $LINENO default_route_dev "Failure retrieving default route device"
 # With the linuxbridge agent, if using VLANs for tenant networks,
 # or if using flat or VLAN provider networks, set in ``localrc`` to
 # the name of the network interface to use for the physical
 # network.
 #
 # Example: ``LB_PHYSICAL_INTERFACE=eth1``
-LB_PHYSICAL_INTERFACE=${LB_PHYSICAL_INTERFACE:-}
+LB_PHYSICAL_INTERFACE=${LB_PHYSICAL_INTERFACE:-$default_route_dev}
 
 # When Neutron tunnels are enabled it is needed to specify the
 # IP address of the end point in the local server. This IP is set
@@ -460,7 +462,7 @@
 
     # Start proxy if enabled
     if is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $Q_PORT $Q_HOST $Q_PORT_INT &
+        start_tls_proxy neutron '*' $Q_PORT $Q_HOST $Q_PORT_INT
     fi
 }
 
diff --git a/lib/neutron_plugins/services/l3 b/lib/neutron_plugins/services/l3
index b598241..408b322 100644
--- a/lib/neutron_plugins/services/l3
+++ b/lib/neutron_plugins/services/l3
@@ -88,8 +88,10 @@
 SUBNETPOOL_SIZE_V4=${SUBNETPOOL_SIZE_V4:-24}
 SUBNETPOOL_SIZE_V6=${SUBNETPOOL_SIZE_V6:-64}
 
-default_route_dev=$(ip route | grep ^default | awk '{print $5}')
-die_if_not_set $LINENO default_route_dev "Failure retrieving default route device"
+default_v4_route_devs=$(ip -4 route | grep ^default | awk '{print $5}')
+die_if_not_set $LINENO default_v4_route_devs "Failure retrieving default IPv4 route devices"
+
+default_v6_route_devs=$(ip -6 route | grep ^default | awk '{print $5}')
 
 function _determine_config_l3 {
     local opts="--config-file $NEUTRON_CONF --config-file $Q_L3_CONF_FILE"
@@ -121,7 +123,9 @@
             _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" False False "inet6"
         fi
     else
-        sudo iptables -t nat -A POSTROUTING -o $default_route_dev -s $FLOATING_RANGE -j MASQUERADE
+        for d in $default_v4_route_devs; do
+            sudo iptables -t nat -A POSTROUTING -o $d -s $FLOATING_RANGE -j MASQUERADE
+        done
     fi
 }
 
@@ -146,6 +150,14 @@
 }
 
 function create_neutron_initial_network {
+    if ! is_service_enabled q-svc && ! is_service_enabled neutron-api; then
+        echo "Controller services not enabled. No networks configured!"
+        return
+    fi
+    if [[ "$NEUTRON_CREATE_INITIAL_NETWORKS" == "False" ]]; then
+        echo "Network creation disabled!"
+        return
+    fi
     local project_id
     project_id=$(openstack project list | grep " demo " | get_field 1)
     die_if_not_set $LINENO project_id "Failure retrieving project_id for demo"
@@ -155,6 +167,15 @@
         neutron_plugin_create_initial_network_profile $PHYSICAL_NETWORK
     fi
 
+    if is_networking_extension_supported "auto-allocated-topology"; then
+        if [[ "$IP_VERSION" =~ 4.* ]]; then
+            SUBNETPOOL_V4_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V4 --pool-prefix $SUBNETPOOL_PREFIX_V4 --shared --is-default=True | grep ' id ' | get_field 2)
+        fi
+        if [[ "$IP_VERSION" =~ .*6 ]]; then
+            SUBNETPOOL_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V6 --pool-prefix $SUBNETPOOL_PREFIX_V6 --shared --is-default=True | grep ' id ' | get_field 2)
+        fi
+    fi
+
     if is_provider_network; then
         die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
         die_if_not_set $LINENO PROVIDER_NETWORK_TYPE "You must specify the PROVIDER_NETWORK_TYPE"
@@ -162,14 +183,20 @@
         die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PHYSICAL_NETWORK $project_id"
 
         if [[ "$IP_VERSION" =~ 4.* ]]; then
-            SUBNET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
+            if [ -z $SUBNETPOOL_V4_ID ]; then
+                fixed_range_v4=$FIXED_RANGE
+            fi
+            SUBNET_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY ${SUBNETPOOL_V4_ID:+--subnetpool $SUBNETPOOL_V4_ID} $NET_ID $fixed_range_v4 | grep ' id ' | get_field 2)
             die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $PROVIDER_SUBNET_NAME $project_id"
         fi
 
         if [[ "$IP_VERSION" =~ .*6 ]]; then
             die_if_not_set $LINENO IPV6_PROVIDER_FIXED_RANGE "IPV6_PROVIDER_FIXED_RANGE has not been set, but Q_USE_PROVIDERNET_FOR_PUBLIC is true and IP_VERSION includes 6"
             die_if_not_set $LINENO IPV6_PROVIDER_NETWORK_GATEWAY "IPV6_PROVIDER_NETWORK_GATEWAY has not been set, but Q_USE_PROVIDERNET_FOR_PUBLIC is true and IP_VERSION includes 6"
-            SUBNET_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME $NET_ID $IPV6_PROVIDER_FIXED_RANGE | grep 'id' | get_field 2)
+            if [ -z $SUBNETPOOL_V6_ID ]; then
+                fixed_range_v6=$IPV6_PROVIDER_FIXED_RANGE
+            fi
+            SUBNET_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create --tenant_id $project_id --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME ${SUBNETPOOL_V6_ID:+--subnetpool $SUBNETPOOL_V6_ID} $NET_ID $fixed_range_v6 | grep 'id' | get_field 2)
             die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $IPV6_PROVIDER_SUBNET_NAME $project_id"
         fi
 
@@ -206,14 +233,8 @@
         fi
 
         EXTERNAL_NETWORK_FLAGS="--router:external"
-        if is_networking_extension_supported "auto-allocated-topology" && is_networking_extension_supported "subnet_allocation"; then
+        if is_networking_extension_supported "auto-allocated-topology"; then
             EXTERNAL_NETWORK_FLAGS="$EXTERNAL_NETWORK_FLAGS --is-default"
-            if [[ "$IP_VERSION" =~ 4.* ]]; then
-                SUBNETPOOL_V4_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V4 --pool-prefix $SUBNETPOOL_PREFIX_V4 --shared --is-default=True | grep ' id ' | get_field 2)
-            fi
-            if [[ "$IP_VERSION" =~ .*6 ]]; then
-                SUBNETPOOL_V6_ID=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnetpool-create $SUBNETPOOL_NAME --default-prefixlen $SUBNETPOOL_SIZE_V6 --pool-prefix $SUBNETPOOL_PREFIX_V6 --shared --is-default=True | grep ' id ' | get_field 2)
-            fi
         fi
         # Create an external network, and a subnet. Configure the external network as router gw
         if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" = "True" ]; then
@@ -238,13 +259,17 @@
 # Create private IPv4 subnet
 function _neutron_create_private_subnet_v4 {
     local project_id=$1
+    if [ -z $SUBNETPOOL_V4_ID ]; then
+        fixed_range_v4=$FIXED_RANGE
+    fi
     local subnet_params="--tenant-id $project_id "
     subnet_params+="--ip_version 4 "
     if [[ -n "$NETWORK_GATEWAY" ]]; then
         subnet_params+="--gateway $NETWORK_GATEWAY "
     fi
     subnet_params+="--name $PRIVATE_SUBNET_NAME "
-    subnet_params+="$NET_ID $FIXED_RANGE"
+    subnet_params+="${SUBNETPOOL_V4_ID:+--subnetpool $SUBNETPOOL_V4_ID} "
+    subnet_params+="$NET_ID $fixed_range_v4"
     local subnet_id
     subnet_id=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep ' id ' | get_field 2)
     die_if_not_set $LINENO subnet_id "Failure creating private IPv4 subnet for $project_id"
@@ -257,13 +282,17 @@
     die_if_not_set $LINENO IPV6_RA_MODE "IPV6 RA Mode not set"
     die_if_not_set $LINENO IPV6_ADDRESS_MODE "IPV6 Address Mode not set"
     local ipv6_modes="--ipv6-ra-mode $IPV6_RA_MODE --ipv6-address-mode $IPV6_ADDRESS_MODE"
+    if [ -z $SUBNETPOOL_V6_ID ]; then
+        fixed_range_v6=$FIXED_RANGE_V6
+    fi
     local subnet_params="--tenant-id $project_id "
     subnet_params+="--ip_version 6 "
     if [[ -n "$IPV6_PRIVATE_NETWORK_GATEWAY" ]]; then
         subnet_params+="--gateway $IPV6_PRIVATE_NETWORK_GATEWAY "
     fi
     subnet_params+="--name $IPV6_PRIVATE_SUBNET_NAME "
-    subnet_params+="$NET_ID $FIXED_RANGE_V6 $ipv6_modes"
+    subnet_params+="${SUBNETPOOL_V6_ID:+--subnetpool $SUBNETPOOL_V6_ID} "
+    subnet_params+="$NET_ID $fixed_range_v6 $ipv6_modes"
     local ipv6_subnet_id
     ipv6_subnet_id=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" subnet-create $subnet_params | grep ' id ' | get_field 2)
     die_if_not_set $LINENO ipv6_subnet_id "Failure creating private IPv6 subnet for $project_id"
@@ -338,7 +367,11 @@
             fi
             ROUTER_GW_IP=$(neutron --os-cloud devstack-admin --os-region "$REGION_NAME" port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F'ip_address'  '{ print $2 }' | cut -f3 -d\" | tr '\n' ' ')
             die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP"
-            sudo ip route replace  $FIXED_RANGE via $ROUTER_GW_IP
+            local replace_range=${SUBNETPOOL_PREFIX_V4}
+            if [[ -z "${SUBNETPOOL_V4_ID}" ]]; then
+                replace_range=${FIXED_RANGE}
+            fi
+            sudo ip route replace $replace_range via $ROUTER_GW_IP
         fi
         _neutron_set_router_id
     fi
@@ -363,11 +396,13 @@
 
     # This logic is specific to using the l3-agent for layer 3
     if is_service_enabled q-l3 || is_service_enabled neutron-l3; then
-        # Ensure IPv6 RAs are accepted on the interface with the default route.
+        # Ensure IPv6 RAs are accepted on interfaces with a default route.
         # This is needed for neutron-based devstack clouds to work in
         # IPv6-only clouds in the gate. Please do not remove this without
         # talking to folks in Infra.
-        sudo sysctl -w net.ipv6.conf.$default_route_dev.accept_ra=2
+        for d in $default_v6_route_devs; do
+            sudo sysctl -w net.ipv6.conf.$d.accept_ra=2
+        done
         # Ensure IPv6 forwarding is enabled on the host
         sudo sysctl -w net.ipv6.conf.all.forwarding=1
         # Configure and enable public bridge
@@ -382,7 +417,11 @@
 
             # Configure interface for public bridge
             sudo ip -6 addr replace $ipv6_ext_gw_ip/$ipv6_cidr_len dev $ext_gw_interface
-            sudo ip -6 route replace $FIXED_RANGE_V6 via $IPV6_ROUTER_GW_IP dev $ext_gw_interface
+            local replace_range=${SUBNETPOOL_PREFIX_V6}
+            if [[ -z "${SUBNETPOOL_V6_ID}" ]]; then
+                replace_range=${FIXED_RANGE_V6}
+            fi
+            sudo ip -6 route replace $replace_range via $IPV6_ROUTER_GW_IP dev $ext_gw_interface
         fi
         _neutron_set_router_id
     fi
diff --git a/lib/nova b/lib/nova
index 235b533..334cba6 100644
--- a/lib/nova
+++ b/lib/nova
@@ -85,6 +85,9 @@
 # NOTE: Set ``FORCE_CONFIG_DRIVE="False"`` to turn OFF config drive
 FORCE_CONFIG_DRIVE=${FORCE_CONFIG_DRIVE:-"False"}
 
+# Option to initialize CellsV2 environment
+NOVA_CONFIGURE_CELLSV2=$(trueorfalse False NOVA_CONFIGURE_CELLSV2)
+
 # Nova supports pluggable schedulers.  The default ``FilterScheduler``
 # should work in most cases.
 SCHEDULER=${SCHEDULER:-filter_scheduler}
@@ -458,7 +461,6 @@
     iniset $NOVA_CONF DEFAULT rootwrap_config "$NOVA_CONF_DIR/rootwrap.conf"
     iniset $NOVA_CONF DEFAULT scheduler_driver "$SCHEDULER"
     iniset $NOVA_CONF DEFAULT scheduler_default_filters "$FILTERS"
-    iniset $NOVA_CONF DEFAULT force_dhcp_release "True"
     iniset $NOVA_CONF DEFAULT default_floating_pool "$PUBLIC_NETWORK_NAME"
     iniset $NOVA_CONF DEFAULT s3_host "$SERVICE_HOST"
     iniset $NOVA_CONF DEFAULT s3_port "$S3_SERVICE_PORT"
@@ -554,7 +556,6 @@
         # For multi-host, this should be the management ip of the compute host.
         VNCSERVER_LISTEN=${VNCSERVER_LISTEN=$NOVA_SERVICE_LOCAL_HOST}
         VNCSERVER_PROXYCLIENT_ADDRESS=${VNCSERVER_PROXYCLIENT_ADDRESS=$NOVA_SERVICE_LOCAL_HOST}
-        iniset $NOVA_CONF vnc enabled true
         iniset $NOVA_CONF vnc vncserver_listen "$VNCSERVER_LISTEN"
         iniset $NOVA_CONF vnc vncserver_proxyclient_address "$VNCSERVER_PROXYCLIENT_ADDRESS"
         iniset $NOVA_CONF vnc novncproxy_host "$NOVA_SERVICE_LISTEN_ADDRESS"
@@ -572,8 +573,6 @@
         iniset $NOVA_CONF spice server_listen "$SPICESERVER_LISTEN"
         iniset $NOVA_CONF spice server_proxyclient_address "$SPICESERVER_PROXYCLIENT_ADDRESS"
         iniset $NOVA_CONF spice html5proxy_host "$NOVA_SERVICE_LISTEN_ADDRESS"
-    else
-        iniset $NOVA_CONF spice enabled false
     fi
 
     # Set the oslo messaging driver to the typical default. This does not
@@ -682,10 +681,15 @@
     # All nova components talk to a central database.
     # Only do this step once on the API node for an entire cluster.
     if is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-api; then
-        # (Re)create nova database
+        # (Re)create nova databases
         recreate_database nova
+        if [ "$NOVA_CONFIGURE_CELLSV2" != "False" ]; then
+            recreate_database nova_api_cell0
+        fi
 
-        # Migrate nova database
+        # Migrate nova database. If "nova-manage cell_v2 simple_cell_setup" has
+        # been run this migrates the "nova" and "nova_api_cell0" database.
+        # Otherwise it just migrates the "nova" database.
         $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF db sync
 
         if is_service_enabled n-cell; then
@@ -800,7 +804,7 @@
 
     # Start proxies if enabled
     if is_service_enabled tls-proxy; then
-        start_tls_proxy '*' $NOVA_SERVICE_PORT $NOVA_SERVICE_HOST $NOVA_SERVICE_PORT_INT &
+        start_tls_proxy nova '*' $NOVA_SERVICE_PORT $NOVA_SERVICE_HOST $NOVA_SERVICE_PORT_INT
     fi
 
     export PATH=$old_path
@@ -823,6 +827,8 @@
         # ``sg`` is used in run_process to execute nova-compute as a member of the
         # **$LIBVIRT_GROUP** group.
         run_process n-cpu "$NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf" $LIBVIRT_GROUP
+    elif [[ "$VIRT_DRIVER" = 'lxd' ]]; then
+        run_process n-cpu "$NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf" $LXD_GROUP
     elif [[ "$VIRT_DRIVER" = 'fake' ]]; then
         local i
         for i in `seq 1 $NUMBER_FAKE_NOVA_COMPUTE`; do
@@ -938,6 +944,15 @@
     fi
 }
 
+# create_cell(): Group the available hosts into a cell
+function create_cell {
+    if ! is_service_enabled n-cell; then
+        nova-manage cell_v2 simple_cell_setup --transport-url $(get_transport_url)
+    else
+        echo 'Skipping cellsv2 setup for this cellsv1 configuration'
+    fi
+}
+
 # Restore xtrace
 $_XTRACE_LIB_NOVA
 
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index cc013c3..6b7c7c2 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -65,6 +65,7 @@
     "/dev/random", "/dev/urandom",
     "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
     "/dev/rtc", "/dev/hpet","/dev/net/tun",
+    "/dev/vfio/vfio",
 ]
 EOF
     fi
diff --git a/lib/nova_plugins/hypervisor-fake b/lib/nova_plugins/hypervisor-fake
index 6ac2199..f9b95c1 100644
--- a/lib/nova_plugins/hypervisor-fake
+++ b/lib/nova_plugins/hypervisor-fake
@@ -45,7 +45,7 @@
     iniset $NOVA_CONF DEFAULT quota_fixed_ips -1
     iniset $NOVA_CONF DEFAULT quota_metadata_items -1
     iniset $NOVA_CONF DEFAULT quota_injected_files -1
-    iniset $NOVA_CONF DEFAULT quota_injected_file_path_bytes -1
+    iniset $NOVA_CONF DEFAULT quota_injected_file_path_length -1
     iniset $NOVA_CONF DEFAULT quota_security_groups -1
     iniset $NOVA_CONF DEFAULT quota_security_group_rules -1
     iniset $NOVA_CONF DEFAULT quota_key_pairs -1
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index 20dde8e..b4eb3c1 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -100,6 +100,14 @@
             yum_install libcgroup-tools
         fi
     fi
+
+    if [[ "$ENABLE_FILE_INJECTION" == "True" ]] ; then
+        if is_ubuntu; then
+            install_package python-guestfs
+        elif is_fedora || is_suse; then
+            install_package python-libguestfs
+        fi
+    fi
 }
 
 # start_nova_hypervisor - Start any required external services
diff --git a/lib/placement b/lib/placement
index 4e80c55..165c670 100644
--- a/lib/placement
+++ b/lib/placement
@@ -40,12 +40,6 @@
 # yet merged in nova but is coming soon.
 PLACEMENT_DB_ENABLED=$(trueorfalse False PLACEMENT_DB_ENABLED)
 
-if is_suse; then
-    PLACEMENT_WSGI_DIR=${PLACEMENT_WSGI_DIR:-/srv/www/htdocs/placement}
-else
-    PLACEMENT_WSGI_DIR=${PLACEMENT_WSGI_DIR:-/var/www/placement}
-fi
-
 if is_ssl_enabled_service "placement-api" || is_service_enabled tls-proxy; then
     PLACEMENT_SERVICE_PROTOCOL="https"
 fi
@@ -73,11 +67,11 @@
 
 # _config_placement_apache_wsgi() - Set WSGI config files
 function _config_placement_apache_wsgi {
-    sudo mkdir -p $PLACEMENT_WSGI_DIR
-
     local placement_api_apache_conf
     local placement_api_port=$PLACEMENT_SERVICE_PORT
     local venv_path=""
+    local nova_bin_dir=""
+    nova_bin_dir=$(get_python_exec_prefix)
     placement_api_apache_conf=$(apache_site_config_for placement-api)
 
     # reuse nova's cert if a cert is being used
@@ -90,16 +84,14 @@
     # 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
     fi
 
-    # copy wsgi application file
-    sudo cp $NOVA_DIR/nova/api/openstack/placement/placement-api.py $PLACEMENT_WSGI_DIR/placement-api
-
     sudo cp $FILES/apache-placement-api.template $placement_api_apache_conf
     sudo sed -e "
         s|%PUBLICPORT%|$placement_api_port|g;
         s|%APACHE_NAME%|$APACHE_NAME|g;
-        s|%PUBLICWSGI%|$PLACEMENT_WSGI_DIR/placement-api|g;
+        s|%PUBLICWSGI%|$nova_bin_dir/nova-placement-api|g;
         s|%SSLENGINE%|$placement_ssl|g;
         s|%SSLCERTFILE%|$placement_certfile|g;
         s|%SSLKEYFILE%|$placement_keyfile|g;
@@ -122,7 +114,7 @@
     iniset $NOVA_CONF placement user_domain_name "Default"
     iniset $NOVA_CONF placement project_name "$SERVICE_TENANT_NAME"
     iniset $NOVA_CONF placement project_domain_name "Default"
-    iniset $NOVA_CONF placement region_name "$REGION_NAME"
+    iniset $NOVA_CONF placement os_region_name "$REGION_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
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 0ee46dc..97b1aa4 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -24,6 +24,8 @@
 _XTRACE_RPC_BACKEND=$(set +o | grep xtrace)
 set +o xtrace
 
+RABBIT_USERID=${RABBIT_USERID:-stackrabbit}
+
 # Functions
 # ---------
 
diff --git a/lib/swift b/lib/swift
index 0c74411..f9ea028 100644
--- a/lib/swift
+++ b/lib/swift
@@ -806,7 +806,7 @@
     done
     if is_service_enabled tls-proxy; then
         local proxy_port=${SWIFT_DEFAULT_BIND_PORT}
-        start_tls_proxy '*' $proxy_port $SERVICE_HOST $SWIFT_DEFAULT_BIND_PORT_INT &
+        start_tls_proxy swift '*' $proxy_port $SERVICE_HOST $SWIFT_DEFAULT_BIND_PORT_INT
     fi
     run_process s-proxy "$SWIFT_DIR/bin/swift-proxy-server ${SWIFT_CONF_DIR}/proxy-server.conf -v"
     if [[ ${SWIFT_REPLICAS} == 1 ]]; then
diff --git a/lib/tempest b/lib/tempest
index 67fb454..b491bf8 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -354,6 +354,8 @@
         iniset $TEMPEST_CONFIG compute max_microversion $tempest_compute_max_microversion
     fi
 
+    # TODO(mriedem): Remove allow_port_security_disabled after liberty-eol.
+    iniset $TEMPEST_CONFIG compute-feature-enabled allow_port_security_disabled True
     iniset $TEMPEST_CONFIG compute-feature-enabled personality ${ENABLE_FILE_INJECTION:-False}
     iniset $TEMPEST_CONFIG compute-feature-enabled resize True
     iniset $TEMPEST_CONFIG compute-feature-enabled live_migration ${LIVE_MIGRATION_AVAILABLE:-False}
diff --git a/lib/tls b/lib/tls
index ca57ed4..2c4e18d 100644
--- a/lib/tls
+++ b/lib/tls
@@ -16,7 +16,6 @@
 #
 # - configure_CA
 # - init_CA
-# - cleanup_CA
 
 # - configure_proxy
 # - start_tls_proxy
@@ -221,19 +220,6 @@
     fi
 }
 
-# Clean up the CA files
-# cleanup_CA
-function cleanup_CA {
-    if is_fedora; then
-        sudo rm -f /usr/share/pki/ca-trust-source/anchors/devstack-chain.pem
-        sudo update-ca-trust
-    elif is_ubuntu; then
-        sudo rm -f /usr/local/share/ca-certificates/devstack-int.crt
-        sudo rm -f /usr/local/share/ca-certificates/devstack-root.crt
-        sudo update-ca-certificates
-    fi
-}
-
 # Create an initial server cert
 # init_cert
 function init_cert {
@@ -455,26 +441,72 @@
 # Starts the TLS proxy for the given IP/ports
 # start_tls_proxy front-host front-port back-host back-port
 function start_tls_proxy {
-    local f_host=$1
-    local f_port=$2
-    local b_host=$3
-    local b_port=$4
+    local b_service="$1-tls-proxy"
+    local f_host=$2
+    local f_port=$3
+    local b_host=$4
+    local b_port=$5
 
-    stud $STUD_PROTO -f $f_host,$f_port -b $b_host,$b_port $DEVSTACK_CERT 2>/dev/null
+    local config_file
+    config_file=$(apache_site_config_for $b_service)
+    local listen_string
+    # Default apache configs on ubuntu and centos listen on 80 and 443
+    # newer apache seems fine with duplicate listen directive but older
+    # apache does not so special case 80 and 443.
+    if [[ "$f_port" == "80" ]] || [[ "$f_port" == "443" ]]; then
+        listen_string=""
+    elif [[ "$f_host" == '*' ]] ; then
+        listen_string="Listen $f_port"
+    else
+        listen_string="Listen $f_host:$f_port"
+    fi
+    sudo bash -c "cat >$config_file" << EOF
+$listen_string
+
+<VirtualHost $f_host:$f_port>
+    SSLEngine On
+    SSLCertificateFile $DEVSTACK_CERT
+
+    <Location />
+        ProxyPass http://$b_host:$b_port/ retry=5 nocanon
+        ProxyPassReverse http://$b_host:$b_port/
+    </Location>
+</VirtualHost>
+EOF
+    for mod in ssl proxy proxy_http; do
+        enable_apache_mod $mod
+    done
+    enable_apache_site $b_service
+    # Only a reload is required to pull in new vhosts
+    # Note that a restart reliably fails on centos7 and trusty
+    # because apache can't open port 80 because the old apache
+    # still has it open. Using reload fixes trusty but centos7
+    # still doesn't work.
+    reload_apache_server
 }
 
 
 # Cleanup Functions
 # =================
 
-# Stops all stud processes. This should be done only after all services
+# Stops the apache service. This should be done only after all services
 # using tls configuration are down.
 function stop_tls_proxy {
-    killall stud
+    stop_apache_server
 }
 
-# Remove CA along with configuration, as well as the local server certificate
+# Clean up the CA files
+# cleanup_CA
 function cleanup_CA {
+    if is_fedora; then
+        sudo rm -f /usr/share/pki/ca-trust-source/anchors/devstack-chain.pem
+        sudo update-ca-trust
+    elif is_ubuntu; then
+        sudo rm -f /usr/local/share/ca-certificates/devstack-int.crt
+        sudo rm -f /usr/local/share/ca-certificates/devstack-root.crt
+        sudo update-ca-certificates
+    fi
+
     rm -rf "$DATA_DIR/CA" "$DEVSTACK_CERT"
 }
 
diff --git a/stack.sh b/stack.sh
index cf157ab..6a5a2a3 100755
--- a/stack.sh
+++ b/stack.sh
@@ -664,7 +664,6 @@
 # Rabbit connection info
 # In multi node DevStack, second node needs ``RABBIT_USERID``, but rabbit
 # isn't enabled.
-RABBIT_USERID=${RABBIT_USERID:-stackrabbit}
 if is_service_enabled rabbit; then
     RABBIT_HOST=${RABBIT_HOST:-$SERVICE_HOST}
     read_password RABBIT_PASSWORD "ENTER A PASSWORD TO USE FOR RABBIT."
@@ -1053,6 +1052,7 @@
 
     if is_service_enabled tls-proxy; then
         echo "export OS_CACERT=$INT_CA_DIR/ca-chain.pem" >> $TOP_DIR/userrc_early
+        start_tls_proxy http-services '*' 443 $SERVICE_HOST 80
     fi
 
     source $TOP_DIR/userrc_early
@@ -1268,10 +1268,7 @@
     start_neutron
 fi
 # Once neutron agents are started setup initial network elements
-if is_service_enabled q-svc && [[ "$NEUTRON_CREATE_INITIAL_NETWORKS" == "True" ]]; then
-    echo_summary "Creating initial neutron network elements"
-    create_neutron_initial_network
-fi
+create_neutron_initial_network
 
 if is_service_enabled nova; then
     echo_summary "Starting Nova"
@@ -1380,11 +1377,24 @@
 check_libs_from_git
 
 
+# Configure nova cellsv2
+# ----------------------
+
+# Do this late because it requires compute hosts to have started
+if is_service_enabled n-api && [ "$NOVA_CONFIGURE_CELLSV2" == "True" ]; then
+    create_cell
+fi
+
 # Bash completion
 # ===============
 
 # Prepare bash completion for OSC
-openstack complete | sudo tee /etc/bash_completion.d/osc.bash_completion > /dev/null
+#
+# BUG: https://bugs.launchpad.net/python-openstackclient/+bug/1619274
+# the os-cloud param should not be required but if we don't provide it
+# then this command hangs indefinitely if something is wrong with
+# default environment credentials.
+openstack --os-cloud=devstack complete | sudo tee /etc/bash_completion.d/osc.bash_completion > /dev/null
 
 # If cinder is configured, set global_filter for PV devices
 if is_service_enabled cinder; then
diff --git a/stackrc b/stackrc
index f7bdbc2..c419ef4 100644
--- a/stackrc
+++ b/stackrc
@@ -16,6 +16,15 @@
 # Destination path for installation
 DEST=/opt/stack
 
+# Destination for working data
+DATA_DIR=${DEST}/data
+
+# Destination for status files
+SERVICE_DIR=${DEST}/status
+
+# Path for subunit output file
+SUBUNIT_OUTPUT=${DEST}/devstack.subunit
+
 # Determine stack user
 if [[ $EUID -eq 0 ]]; then
     STACK_USER=stack
@@ -121,15 +130,6 @@
     source $RC_DIR/.localrc.auto
 fi
 
-# Destination for working data
-DATA_DIR=${DATA_DIR:-$DEST/data}
-
-# Destination for status files
-SERVICE_DIR=${SERVICE_DIR:-$DEST/status}
-
-# Path for subunit output file
-SUBUNIT_OUTPUT=${SUBUNIT_OUTPUT:-$DEST/devstack.subunit}
-
 # Default for log coloring is based on interactive-or-not.
 # Baseline assumption is that non-interactive invocations are for CI,
 # where logs are to be presented as browsable text files; hence color
@@ -586,6 +586,9 @@
             LIBVIRT_GROUP=libvirtd
         fi
         ;;
+    lxd)
+        LXD_GROUP=${LXD_GROUP:-"lxd"}
+        ;;
     fake)
         NUMBER_FAKE_NOVA_COMPUTE=${NUMBER_FAKE_NOVA_COMPUTE:-1}
         ;;
diff --git a/tools/generate-devstack-plugins-list.py b/tools/generate-devstack-plugins-list.py
index bbad1bf..56f12e7 100644
--- a/tools/generate-devstack-plugins-list.py
+++ b/tools/generate-devstack-plugins-list.py
@@ -46,6 +46,9 @@
 
 # Check if this project has a plugin file
 def has_devstack_plugin(proj):
+    # Don't link in the deb packaging repos
+    if "openstack/deb-" in proj:
+        return False
     r = requests.get("https://git.openstack.org/cgit/%s/plain/devstack/plugin.sh" % proj)
     return r.status_code == 200
 
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index 1267699..a5ccb19 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -24,7 +24,20 @@
 
 FILES=$TOP_DIR/files
 
-PIP_GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py
+# The URL from where the get-pip.py file gets downloaded. If a local
+# get-pip.py mirror is available, PIP_GET_PIP_URL can be set to that
+# mirror in local.conf to avoid download timeouts.
+# Example:
+#  PIP_GET_PIP_URL="http://local-server/get-pip.py"
+#
+# Note that if get-pip.py already exists in $FILES this script will
+# not re-download or check for a new version.  For example, this is
+# done by openstack-infra diskimage-builder elements as part of image
+# preparation [1].  This prevents any network access, which can be
+# unreliable in CI situations.
+# [1] http://git.openstack.org/cgit/openstack-infra/project-config/tree/nodepool/elements/cache-devstack/source-repository-pip
+
+PIP_GET_PIP_URL=${PIP_GET_PIP_URL:-"https://bootstrap.pypa.io/get-pip.py"}
 LOCAL_PIP="$FILES/$(basename $PIP_GET_PIP_URL)"
 
 GetDistro