Merge "Always set the Heat deferred auth method"
diff --git a/clean.sh b/clean.sh
index ad4525b..035489c 100755
--- a/clean.sh
+++ b/clean.sh
@@ -49,7 +49,7 @@
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ironic
 source $TOP_DIR/lib/trove
 
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 7d06658..a0d0840 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -170,6 +170,30 @@
 
       LIBS_FROM_GIT=python-keystoneclient,oslo.config
 
+Virtual Environments
+--------------------
+
+  | *Default: ``USE_VENV=False``*
+  |   Enable the use of Python virtual environments by setting ``USE_VENV``
+      to ``True``.  This will enable the creation of venvs for each project
+      that is defined in the ``PROJECT_VENV`` array.
+
+  | *Default: ``PROJECT_VENV['<project>']='<project-dir>.venv'*
+  |   Each entry in the ``PROJECT_VENV`` array contains the directory name
+      of a venv to be used for the project.  The array index is the project
+      name.  Multiple projects can use the same venv if desired.
+
+  ::
+
+    PROJECT_VENV["glance"]=${GLANCE_DIR}.venv
+
+  | *Default: ``ADDITIONAL_VENV_PACKAGES=""``*
+  |   A comma-separated list of additional packages to be installed into each
+      venv.  Often projects will not have certain packages listed in its
+      ``requirements.txt`` file because they are 'optional' requirements,
+      i.e. only needed for certain configurations.  By default, the enabled
+      databases will have their Python bindings added when they are enabled.
+
 Enable Logging
 --------------
 
@@ -247,6 +271,21 @@
 
         RECLONE=yes
 
+Upgrade packages installed by pip
+---------------------------------
+
+    | *Default: ``PIP_UPGRADE=""``*
+    |  By default ``stack.sh`` only installs Python packages if no version
+       is currently installed or the current version does not match a specified
+       requirement. If ``PIP_UPGRADE`` is set to ``True`` then existing required
+       Python packages will be upgraded to the most recent version that
+       matches requirements.
+    |
+
+    ::
+
+        PIP_UPGRADE=True
+
 Swift
 -----
 
@@ -378,18 +417,6 @@
       can be configured with any valid IPv6 prefix. The default values make
       use of an auto-generated ``IPV6_GLOBAL_ID`` to comply with RFC 4193.*
 
-Unit tests dependencies install
--------------------------------
-
-    | *Default: ``INSTALL_TESTONLY_PACKAGES=False``*
-    |  In order to be able to run unit tests with script ``run_test.sh``,
-       the required package dependencies need to be installed.
-       Setting this option as below does the work.
-
-    ::
-
-        INSTALL_TESTONLY_PACKAGES=True
-
 Examples
 ========
 
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 537f657..c31287c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -166,7 +166,7 @@
 * `lib/ironic <lib/ironic.html>`__
 * `lib/keystone <lib/keystone.html>`__
 * `lib/ldap <lib/ldap.html>`__
-* `lib/neutron <lib/neutron.html>`__
+* `lib/neutron-legacy <lib/neutron-legacy.html>`__
 * `lib/nova <lib/nova.html>`__
 * `lib/oslo <lib/oslo.html>`__
 * `lib/rpc\_backend <lib/rpc_backend.html>`__
@@ -211,6 +211,8 @@
 -----
 
 * `tools/build\_docs.sh <tools/build_docs.sh.html>`__
+* `tools/build\_venv.sh <tools/build_venv.sh.html>`__
+* `tools/build\_wheels.sh <tools/build_wheels.sh.html>`__
 * `tools/create-stack-user.sh <tools/create-stack-user.sh.html>`__
 * `tools/create\_userrc.sh <tools/create_userrc.sh.html>`__
 * `tools/fixup\_stuff.sh <tools/fixup_stuff.sh.html>`__
diff --git a/doc/source/plugins.rst b/doc/source/plugins.rst
index 5a61063..c4ed228 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -113,6 +113,11 @@
   services using ``run_process`` as it only works with enabled
   services.
 
+  Be careful to allow users to override global-variables for
+  customizing their environment.  Usually it is best to provide a
+  default value only if the variable is unset or empty; e.g. in bash
+  syntax ``FOO=${FOO:-default}``.
+
 - ``plugin.sh`` - the actual plugin. It will be executed by devstack
   during it's run. The run order will be done in the registration
   order for these plugins, and will occur immediately after all in
diff --git a/exercises/boot_from_volume.sh b/exercises/boot_from_volume.sh
index a2ae275..aa34830 100755
--- a/exercises/boot_from_volume.sh
+++ b/exercises/boot_from_volume.sh
@@ -32,7 +32,7 @@
 
 # Import project functions
 source $TOP_DIR/lib/cinder
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 
 # Import configuration
 source $TOP_DIR/openrc
diff --git a/exercises/euca.sh b/exercises/euca.sh
index f9c4752..df5e233 100755
--- a/exercises/euca.sh
+++ b/exercises/euca.sh
@@ -37,7 +37,7 @@
 source $TOP_DIR/exerciserc
 
 # Import project functions
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 
 # If nova api is not enabled we exit with exitcode 55 so that
 # the exercise is skipped
diff --git a/exercises/floating_ips.sh b/exercises/floating_ips.sh
index 57f48e0..59444e1 100755
--- a/exercises/floating_ips.sh
+++ b/exercises/floating_ips.sh
@@ -31,7 +31,7 @@
 source $TOP_DIR/openrc
 
 # Import project functions
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 
 # Import exercise configuration
 source $TOP_DIR/exerciserc
diff --git a/exercises/neutron-adv-test.sh b/exercises/neutron-adv-test.sh
index 5b3281b..9230587 100755
--- a/exercises/neutron-adv-test.sh
+++ b/exercises/neutron-adv-test.sh
@@ -49,7 +49,7 @@
 source $TOP_DIR/openrc
 
 # Import neutron functions
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 
 # If neutron is not enabled we exit with exitcode 55, which means exercise is skipped.
 neutron_plugin_check_adv_test_requirements || exit 55
diff --git a/exercises/volumes.sh b/exercises/volumes.sh
index 504fba1..3ac2016 100755
--- a/exercises/volumes.sh
+++ b/exercises/volumes.sh
@@ -32,7 +32,7 @@
 
 # Import project functions
 source $TOP_DIR/lib/cinder
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 
 # Import exercise configuration
 source $TOP_DIR/exerciserc
diff --git a/files/apache-keystone.template b/files/apache-keystone.template
index 504dc01..1d20af7 100644
--- a/files/apache-keystone.template
+++ b/files/apache-keystone.template
@@ -2,7 +2,7 @@
 Listen %ADMINPORT%
 
 <VirtualHost *:%PUBLICPORT%>
-    WSGIDaemonProcess keystone-public processes=5 threads=1 user=%USER% display-name=%{GROUP}
+    WSGIDaemonProcess keystone-public processes=5 threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
     WSGIProcessGroup keystone-public
     WSGIScriptAlias / %PUBLICWSGI%
     WSGIApplicationGroup %{GLOBAL}
@@ -18,7 +18,7 @@
 </VirtualHost>
 
 <VirtualHost *:%ADMINPORT%>
-    WSGIDaemonProcess keystone-admin processes=5 threads=1 user=%USER% display-name=%{GROUP}
+    WSGIDaemonProcess keystone-admin processes=5 threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
     WSGIProcessGroup keystone-admin
     WSGIScriptAlias / %ADMINWSGI%
     WSGIApplicationGroup %{GLOBAL}
diff --git a/files/debs/cinder b/files/debs/cinder
index 7819c31..51908eb 100644
--- a/files/debs/cinder
+++ b/files/debs/cinder
@@ -1,4 +1,4 @@
-tgt
+tgt # NOPRIME
 lvm2
 qemu-utils
 libpq-dev
diff --git a/files/debs/general b/files/debs/general
index 5f10a20..c27b77d 100644
--- a/files/debs/general
+++ b/files/debs/general
@@ -23,3 +23,4 @@
 libssl-dev # for pyOpenSSL
 gettext  # used for compiling message catalogs
 openjdk-7-jre-headless  # NOPRIME
+pkg-config
diff --git a/files/rpms-suse/cinder b/files/rpms-suse/cinder
index 55078da..3fd03cc 100644
--- a/files/rpms-suse/cinder
+++ b/files/rpms-suse/cinder
@@ -1,5 +1,5 @@
 lvm2
-tgt
+tgt # NOPRIME
 qemu-tools
 python-devel
 postgresql-devel
diff --git a/files/rpms/cinder b/files/rpms/cinder
index 9f1359f..a88503b 100644
--- a/files/rpms/cinder
+++ b/files/rpms/cinder
@@ -1,5 +1,5 @@
 lvm2
-scsi-target-utils
+scsi-target-utils # NOPRIME
 qemu-img
 postgresql-devel
 iscsi-initiator-utils
diff --git a/files/rpms/general b/files/rpms/general
index d74ecc6..bc0d6c7 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -12,6 +12,7 @@
 libffi-devel
 libxml2-devel
 libxslt-devel
+pkgconfig
 psmisc
 pylint
 python-devel
diff --git a/functions-common b/functions-common
index 48e400d..0f80e98 100644
--- a/functions-common
+++ b/functions-common
@@ -909,8 +909,6 @@
     local file_to_parse=""
     local service=""
 
-    INSTALL_TESTONLY_PACKAGES=$(trueorfalse False INSTALL_TESTONLY_PACKAGES)
-
     if [[ -z "$package_dir" ]]; then
         echo "No package directory supplied"
         return 1
@@ -1501,6 +1499,33 @@
     done
 }
 
+# plugin_override_defaults
+#
+# Run an extremely early setting phase for plugins that allows default
+# overriding of services.
+function plugin_override_defaults {
+    local plugins="${DEVSTACK_PLUGINS}"
+    local plugin
+
+    # short circuit if nothing to do
+    if [[ -z $plugins ]]; then
+        return
+    fi
+
+    echo "Overriding Configuration Defaults"
+    for plugin in ${plugins//,/ }; do
+        local dir=${GITDIR[$plugin]}
+        # source any overrides
+        if [[ -f $dir/devstack/override-defaults ]]; then
+            # be really verbose that an override is happening, as it
+            # may not be obvious if things fail later.
+            echo "$plugin has overriden the following defaults"
+            cat $dir/devstack/override-defaults
+            source $dir/devstack/override-defaults
+        fi
+    done
+}
+
 # run_plugins
 #
 # Run the devstack/plugin.sh in all the plugin directories. These are
@@ -1530,6 +1555,8 @@
     # the source phase corresponds to settings loading in plugins
     if [[ "$mode" == "source" ]]; then
         load_plugin_settings
+    elif [[ "$mode" == "override_defaults" ]]; then
+        plugin_override_defaults
     else
         run_plugins $mode $phase
     fi
diff --git a/inc/python b/inc/python
index 2d76081..39684b6 100644
--- a/inc/python
+++ b/inc/python
@@ -53,18 +53,24 @@
 }
 
 # Wrapper for ``pip install`` to set cache and proxy environment variables
-# Uses globals ``INSTALL_TESTONLY_PACKAGES``, ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
-# ``TRACK_DEPENDS``, ``*_proxy``
+# Uses globals ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
+# ``PIP_UPGRADE``, ``TRACK_DEPENDS``, ``*_proxy``
 # pip_install package [package ...]
 function pip_install {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local upgrade=""
     local offline=${OFFLINE:-False}
     if [[ "$offline" == "True" || -z "$@" ]]; then
         $xtrace
         return
     fi
 
+    PIP_UPGRADE=$(trueorfalse False PIP_UPGRADE)
+    if [[ "$PIP_UPGRADE" = "True" ]] ; then
+        upgrade="--upgrade"
+    fi
+
     if [[ -z "$os_PACKAGE" ]]; then
         GetOSVersion
     fi
@@ -98,7 +104,7 @@
         https_proxy="${https_proxy:-}" \
         no_proxy="${no_proxy:-}" \
         PIP_FIND_LINKS=$PIP_FIND_LINKS \
-        $cmd_pip install \
+        $cmd_pip install $upgrade \
         $@
 
     # Also install test requirements
@@ -110,7 +116,7 @@
             https_proxy=${https_proxy:-} \
             no_proxy=${no_proxy:-} \
             PIP_FIND_LINKS=$PIP_FIND_LINKS \
-            $cmd_pip install \
+            $cmd_pip install $upgrade \
             -r $test_req
     fi
 }
diff --git a/lib/cinder b/lib/cinder
index ef68d8d..27fd692 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -39,8 +39,16 @@
 
 # set up default directories
 GITDIR["python-cinderclient"]=$DEST/python-cinderclient
-
 CINDER_DIR=$DEST/cinder
+
+# Cinder virtual environment
+if [[ ${USE_VENV} = True ]]; then
+    PROJECT_VENV["cinder"]=${CINDER_DIR}.venv
+    CINDER_BIN_DIR=${PROJECT_VENV["cinder"]}/bin
+else
+    CINDER_BIN_DIR=$(get_python_exec_prefix)
+fi
+
 CINDER_STATE_PATH=${CINDER_STATE_PATH:=$DATA_DIR/cinder}
 CINDER_AUTH_CACHE_DIR=${CINDER_AUTH_CACHE_DIR:-/var/cache/cinder}
 
@@ -57,13 +65,6 @@
 CINDER_SERVICE_PORT_INT=${CINDER_SERVICE_PORT_INT:-18776}
 CINDER_SERVICE_PROTOCOL=${CINDER_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
 
-# Support entry points installation of console scripts
-if [[ -d $CINDER_DIR/bin ]]; then
-    CINDER_BIN_DIR=$CINDER_DIR/bin
-else
-    CINDER_BIN_DIR=$(get_python_exec_prefix)
-fi
-
 
 # Default backends
 # The backend format is type:name where type is one of the supported backend
@@ -88,6 +89,8 @@
 # https://bugs.launchpad.net/cinder/+bug/1180976
 CINDER_PERIODIC_INTERVAL=${CINDER_PERIODIC_INTERVAL:-60}
 
+CINDER_ISCSI_HELPER=${CINDER_ISCSI_HELPER:-tgtadm}
+
 # Tell Tempest this project is present
 TEMPEST_SERVICES+=,cinder
 
@@ -125,31 +128,35 @@
 function cleanup_cinder {
     # ensure the volume group is cleared up because fails might
     # leave dead volumes in the group
-    local targets=$(sudo tgtadm --op show --mode target)
-    if [ $? -ne 0 ]; then
-        # If tgt driver isn't running this won't work obviously
-        # So check the response and restart if need be
-        echo "tgtd seems to be in a bad state, restarting..."
-        if is_ubuntu; then
-            restart_service tgt
-        else
-            restart_service tgtd
+    if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
+        local targets=$(sudo tgtadm --op show --mode target)
+        if [ $? -ne 0 ]; then
+            # If tgt driver isn't running this won't work obviously
+            # So check the response and restart if need be
+            echo "tgtd seems to be in a bad state, restarting..."
+            if is_ubuntu; then
+                restart_service tgt
+            else
+                restart_service tgtd
+            fi
+            targets=$(sudo tgtadm --op show --mode target)
         fi
-        targets=$(sudo tgtadm --op show --mode target)
-    fi
 
-    if [[ -n "$targets" ]]; then
-        local iqn_list=( $(grep --no-filename -r iqn $SCSI_PERSIST_DIR | sed 's/<target //' | sed 's/>//') )
-        for i in "${iqn_list[@]}"; do
-            echo removing iSCSI target: $i
-            sudo tgt-admin --delete $i
-        done
-    fi
+        if [[ -n "$targets" ]]; then
+            local iqn_list=( $(grep --no-filename -r iqn $SCSI_PERSIST_DIR | sed 's/<target //' | sed 's/>//') )
+            for i in "${iqn_list[@]}"; do
+                echo removing iSCSI target: $i
+                sudo tgt-admin --delete $i
+            done
+        fi
 
-    if is_ubuntu; then
-        stop_service tgt
+        if is_ubuntu; then
+            stop_service tgt
+        else
+            stop_service tgtd
+        fi
     else
-        stop_service tgtd
+        sudo cinder-rtstool get-targets | sudo xargs -rn 1 cinder-rtstool delete
     fi
 
     if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
@@ -164,12 +171,11 @@
     fi
 }
 
+# Deploy new rootwrap filters files and configure sudo
 # configure_cinder_rootwrap() - configure Cinder's rootwrap
 function configure_cinder_rootwrap {
-    # Set the paths of certain binaries
-    local cinder_rootwrap=$(get_rootwrap_location cinder)
+    local cinder_rootwrap=$CINDER_BIN_DIR/cinder-rootwrap
 
-    # Deploy new rootwrap filters files (owned by root).
     # Wipe any existing rootwrap.d files first
     if [[ -d $CINDER_CONF_DIR/rootwrap.d ]]; then
         sudo rm -rf $CINDER_CONF_DIR/rootwrap.d
@@ -188,10 +194,17 @@
 
     # Set up the rootwrap sudoers for cinder
     local tempfile=`mktemp`
-    echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_CSUDOER_CMD" >$tempfile
+    echo "Defaults:$STACK_USER secure_path=$CINDER_BIN_DIR:/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >$tempfile
+    echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_CSUDOER_CMD" >>$tempfile
     chmod 0440 $tempfile
     sudo chown root:root $tempfile
     sudo mv $tempfile /etc/sudoers.d/cinder-rootwrap
+
+    # So rootwrap and PATH are broken beyond belief.  WTF relies on a SECURE operation
+    # to blindly follow PATH???  We learned that was a bad idea in the 80's!
+    # So to fix this in a venv, we must exploit the very hole we want to close by dropping
+    # a copy of the venv rootwrap binary into /usr/local/bin.
+    #sudo cp -p $cinder_rootwrap /usr/local/bin
 }
 
 # configure_cinder() - Set config files, create data dirs, etc
@@ -224,7 +237,7 @@
     iniset $CINDER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $CINDER_CONF DEFAULT verbose True
 
-    iniset $CINDER_CONF DEFAULT iscsi_helper tgtadm
+    iniset $CINDER_CONF DEFAULT iscsi_helper "$CINDER_ISCSI_HELPER"
     iniset $CINDER_CONF database connection `database_connection_url cinder`
     iniset $CINDER_CONF DEFAULT api_paste_config $CINDER_API_PASTE_INI
     iniset $CINDER_CONF DEFAULT rootwrap_config "$CINDER_CONF_DIR/rootwrap.conf"
@@ -388,6 +401,13 @@
 function install_cinder {
     git_clone $CINDER_REPO $CINDER_DIR $CINDER_BRANCH
     setup_develop $CINDER_DIR
+    if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
+        if is_fedora; then
+            install_package scsi-target-utils
+        else
+            install_package tgt
+        fi
+    fi
 }
 
 # install_cinderclient() - Collect source and prepare
@@ -415,21 +435,23 @@
         service_port=$CINDER_SERVICE_PORT_INT
         service_protocol="http"
     fi
-    if is_service_enabled c-vol; then
-        # Delete any old stack.conf
-        sudo rm -f /etc/tgt/conf.d/stack.conf
-        _configure_tgt_for_config_d
-        if is_ubuntu; then
-            sudo service tgt restart
-        elif is_fedora || is_suse; then
-            restart_service tgtd
-        else
-            # note for other distros: unstack.sh also uses the tgt/tgtd service
-            # name, and would need to be adjusted too
-            exit_distro_not_supported "restarting tgt"
+    if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
+        if is_service_enabled c-vol; then
+            # Delete any old stack.conf
+            sudo rm -f /etc/tgt/conf.d/stack.conf
+            _configure_tgt_for_config_d
+            if is_ubuntu; then
+                sudo service tgt restart
+            elif is_fedora || is_suse; then
+                restart_service tgtd
+            else
+                # note for other distros: unstack.sh also uses the tgt/tgtd service
+                # name, and would need to be adjusted too
+                exit_distro_not_supported "restarting tgt"
+            fi
+            # NOTE(gfidente): ensure tgtd is running in debug mode
+            sudo tgtadm --mode system --op update --name debug --value on
         fi
-        # NOTE(gfidente): ensure tgtd is running in debug mode
-        sudo tgtadm --mode system --op update --name debug --value on
     fi
 
     run_process c-api "$CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF"
@@ -459,14 +481,6 @@
     for serv in c-api c-bak c-sch c-vol; do
         stop_process $serv
     done
-
-    if is_service_enabled c-vol; then
-        if is_ubuntu; then
-            stop_service tgt
-        else
-            stop_service tgtd
-        fi
-    fi
 }
 
 # create_volume_types() - Create Cinder's configured volume types
diff --git a/lib/cinder_backends/lvm b/lib/cinder_backends/lvm
index f210578..d369c0c 100644
--- a/lib/cinder_backends/lvm
+++ b/lib/cinder_backends/lvm
@@ -49,7 +49,7 @@
     iniset $CINDER_CONF $be_name volume_backend_name $be_name
     iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.lvm.LVMVolumeDriver"
     iniset $CINDER_CONF $be_name volume_group $VOLUME_GROUP_NAME-$be_name
-    iniset $CINDER_CONF $be_name iscsi_helper "tgtadm"
+    iniset $CINDER_CONF $be_name iscsi_helper "$CINDER_ISCSI_HELPER"
 
     if [[ "$CINDER_SECURE_DELETE" == "False" ]]; then
         iniset $CINDER_CONF $be_name volume_clear none
diff --git a/lib/database b/lib/database
index b114e9e..ff1fafe 100644
--- a/lib/database
+++ b/lib/database
@@ -109,6 +109,11 @@
     install_database_$DATABASE_TYPE
 }
 
+# Install the database Python packages
+function install_database_python {
+    install_database_python_$DATABASE_TYPE
+}
+
 # Configure and start the database
 function configure_database {
     configure_database_$DATABASE_TYPE
diff --git a/lib/databases/mysql b/lib/databases/mysql
index dabd7d0..310817b 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -151,9 +151,12 @@
     else
         exit_distro_not_supported "mysql installation"
     fi
+}
 
+function install_database_python_mysql {
     # Install Python client module
     pip_install MySQL-python
+    ADDITIONAL_VENV_PACKAGES+=",MySQL-python"
 }
 
 function database_connection_url_mysql {
diff --git a/lib/databases/postgresql b/lib/databases/postgresql
index e891a08..a6bcf8c 100644
--- a/lib/databases/postgresql
+++ b/lib/databases/postgresql
@@ -100,9 +100,12 @@
     else
         exit_distro_not_supported "postgresql installation"
     fi
+}
 
+function install_database_python_postgresql {
     # Install Python client module
     pip_install psycopg2
+    ADDITIONAL_VENV_PACKAGES+=",psycopg2"
 }
 
 function database_connection_url_postgresql {
diff --git a/lib/glance b/lib/glance
index d781056..578c88a 100755
--- a/lib/glance
+++ b/lib/glance
@@ -31,8 +31,16 @@
 # Set up default directories
 GITDIR["python-glanceclient"]=$DEST/python-glanceclient
 GITDIR["glance_store"]=$DEST/glance_store
-
 GLANCE_DIR=$DEST/glance
+
+# Glance virtual environment
+if [[ ${USE_VENV} = True ]]; then
+    PROJECT_VENV["glance"]=${GLANCE_DIR}.venv
+    GLANCE_BIN_DIR=${PROJECT_VENV["glance"]}/bin
+else
+    GLANCE_BIN_DIR=$(get_python_exec_prefix)
+fi
+
 GLANCE_CACHE_DIR=${GLANCE_CACHE_DIR:=$DATA_DIR/glance/cache}
 GLANCE_IMAGE_DIR=${GLANCE_IMAGE_DIR:=$DATA_DIR/glance/images}
 GLANCE_AUTH_CACHE_DIR=${GLANCE_AUTH_CACHE_DIR:-/var/cache/glance}
@@ -47,13 +55,6 @@
 GLANCE_POLICY_JSON=$GLANCE_CONF_DIR/policy.json
 GLANCE_SCHEMA_JSON=$GLANCE_CONF_DIR/schema-image.json
 
-# Support entry points installation of console scripts
-if [[ -d $GLANCE_DIR/bin ]]; then
-    GLANCE_BIN_DIR=$GLANCE_DIR/bin
-else
-    GLANCE_BIN_DIR=$(get_python_exec_prefix)
-fi
-
 if is_ssl_enabled_service "glance" || is_service_enabled tls-proxy; then
     GLANCE_SERVICE_PROTOCOL="https"
 fi
diff --git a/lib/ironic b/lib/ironic
index 58cc2fa..a7738bc 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -181,7 +181,11 @@
 # install_ironic() - Collect source and prepare
 function install_ironic {
     # make sure all needed service were enabled
-    for srv in nova glance key; do
+    local req_services="key"
+    if [[ "$VIRT_DRIVER" == "ironic" ]]; then
+        req_services+=" nova glance neutron"
+    fi
+    for srv in $req_services; do
         if ! is_service_enabled "$srv"; then
             die $LINENO "$srv should be enabled for Ironic."
         fi
diff --git a/lib/keystone b/lib/keystone
index 23773fa..1e39ab6 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -37,8 +37,16 @@
 # Set up default directories
 GITDIR["python-keystoneclient"]=$DEST/python-keystoneclient
 GITDIR["keystonemiddleware"]=$DEST/keystonemiddleware
-
 KEYSTONE_DIR=$DEST/keystone
+
+# Keystone virtual environment
+if [[ ${USE_VENV} = True ]]; then
+    PROJECT_VENV["keystone"]=${KEYSTONE_DIR}.venv
+    KEYSTONE_BIN_DIR=${PROJECT_VENV["keystone"]}/bin
+else
+    KEYSTONE_BIN_DIR=$(get_python_exec_prefix)
+fi
+
 KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/keystone}
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
 KEYSTONE_PASTE_INI=${KEYSTONE_PASTE_INI:-$KEYSTONE_CONF_DIR/keystone-paste.ini}
@@ -144,6 +152,7 @@
     local keystone_keyfile=""
     local keystone_service_port=$KEYSTONE_SERVICE_PORT
     local keystone_auth_port=$KEYSTONE_AUTH_PORT
+    local venv_path=""
 
     if is_ssl_enabled_service key; then
         keystone_ssl="SSLEngine On"
@@ -154,6 +163,9 @@
         keystone_service_port=$KEYSTONE_SERVICE_PORT_INT
         keystone_auth_port=$KEYSTONE_AUTH_PORT_INT
     fi
+    if [[ ${USE_VENV} = True ]]; then
+        venv_path="python-path=${PROJECT_VENV["keystone"]}/lib/python2.7/site-packages"
+    fi
 
     # copy proxy vhost and wsgi file
     sudo cp $KEYSTONE_DIR/httpd/keystone.py $KEYSTONE_WSGI_DIR/main
@@ -169,7 +181,8 @@
         s|%SSLENGINE%|$keystone_ssl|g;
         s|%SSLCERTFILE%|$keystone_certfile|g;
         s|%SSLKEYFILE%|$keystone_keyfile|g;
-        s|%USER%|$STACK_USER|g
+        s|%USER%|$STACK_USER|g;
+        s|%VIRTUALENV%|$venv_path|g
     " -i $keystone_apache_conf
 }
 
@@ -460,20 +473,20 @@
     recreate_database keystone
 
     # Initialize keystone database
-    $KEYSTONE_DIR/bin/keystone-manage db_sync
+    $KEYSTONE_BIN_DIR/keystone-manage db_sync
 
     local extension_value
     for extension_value in ${KEYSTONE_EXTENSIONS//,/ }; do
         if [[ -z "${extension_value}" ]]; then
             continue
         fi
-        $KEYSTONE_DIR/bin/keystone-manage db_sync --extension "${extension_value}"
+        $KEYSTONE_BIN_DIR/keystone-manage db_sync --extension "${extension_value}"
     done
 
     if [[ "$KEYSTONE_TOKEN_FORMAT" != "uuid" ]]; then
         # Set up certificates
         rm -rf $KEYSTONE_CONF_DIR/ssl
-        $KEYSTONE_DIR/bin/keystone-manage pki_setup
+        $KEYSTONE_BIN_DIR/keystone-manage pki_setup
 
         # Create cache dir
         sudo install -d -o $STACK_USER $KEYSTONE_AUTH_CACHE_DIR
@@ -492,9 +505,14 @@
 
 # install_keystonemiddleware() - Collect source and prepare
 function install_keystonemiddleware {
+    # install_keystonemiddleware() is called when keystonemiddleware is needed
+    # to provide an opportunity to install it from the source repo
     if use_library_from_git "keystonemiddleware"; then
         git_clone_by_name "keystonemiddleware"
         setup_dev_lib "keystonemiddleware"
+    else
+        # When not installing from repo, keystonemiddleware is still needed...
+        pip_install keystonemiddleware
     fi
 }
 
@@ -542,7 +560,7 @@
         tail_log key-access /var/log/$APACHE_NAME/keystone_access.log
     else
         # Start Keystone in a screen window
-        run_process key "$KEYSTONE_DIR/bin/keystone-all --config-file $KEYSTONE_CONF"
+        run_process key "$KEYSTONE_BIN_DIR/keystone-all --config-file $KEYSTONE_CONF"
     fi
 
     echo "Waiting for keystone to start..."
diff --git a/lib/lvm b/lib/lvm
index d0322c7..519e82c 100644
--- a/lib/lvm
+++ b/lib/lvm
@@ -108,15 +108,20 @@
     if is_fedora || is_suse; then
         # services is not started by default
         start_service lvm2-lvmetad
-        start_service tgtd
+        if [ "$CINDER_ISCSI_HELPER" = "tgtadm" ]; then
+            start_service tgtd
+        fi
     fi
 
     # Start with a clean volume group
     _create_lvm_volume_group $vg $size
 
     # Remove iscsi targets
-    sudo tgtadm --op show --mode target | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
-
+    if [ "$CINDER_ISCSI_HELPER" = "lioadm" ]; then
+        sudo cinder-rtstool get-targets | sudo xargs -rn 1 cinder-rtstool delete
+    else
+        sudo tgtadm --op show --mode target | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
+    fi
     _clean_lvm_volume_group $vg
 }
 
diff --git a/lib/neutron b/lib/neutron
new file mode 120000
index 0000000..00cd722
--- /dev/null
+++ b/lib/neutron
@@ -0,0 +1 @@
+neutron-legacy
\ No newline at end of file
diff --git a/lib/neutron b/lib/neutron-legacy
similarity index 96%
rename from lib/neutron
rename to lib/neutron-legacy
index 5ff3921..d3dd8dd 100755
--- a/lib/neutron
+++ b/lib/neutron-legacy
@@ -779,9 +779,41 @@
     fi
 }
 
+# _move_neutron_addresses_route() - Move the primary IP to the OVS bridge
+# on startup, or back to the public interface on cleanup
+function _move_neutron_addresses_route {
+    local from_intf=$1
+    local to_intf=$2
+    local add_ovs_port=$3
+
+    if [[ -n "$from_intf" && -n "$to_intf" ]]; then
+        # Remove the primary IP address from $from_intf and add it to $to_intf,
+        # along with the default route, if it exists.  Also, when called
+        # on configure we will also add $from_intf as a port on $to_intf,
+        # assuming it is an OVS bridge.
+
+        local IP_BRD=$(ip -4 a s dev $from_intf | awk '/inet/ { print $2, $3, $4; exit }')
+        local DEFAULT_ROUTE_GW=$(ip r | awk "/default.+$from_intf/ { print \$3; exit }")
+        local ADD_OVS_PORT=""
+
+        if [ "$DEFAULT_ROUTE_GW" != "" ]; then
+            ADD_DEFAULT_ROUTE="sudo ip r replace default via $DEFAULT_ROUTE_GW dev $to_intf"
+        fi
+
+        if [[ "$add_ovs_port" == "True" ]]; then
+            ADD_OVS_PORT="sudo ovs-vsctl add-port $to_intf $from_intf"
+        fi
+
+        sudo ip addr del $IP_BRD dev $from_intf; sudo ip addr add $IP_BRD dev $to_intf; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
+    fi
+}
+
 # cleanup_neutron() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_neutron {
+
+    _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False
+
     if is_provider_network && is_ironic_hardware; then
         for IP in $(ip addr show dev $OVS_PHYSICAL_BRIDGE | grep ' inet ' | awk '{print $2}'); do
             sudo ip addr del $IP dev $OVS_PHYSICAL_BRIDGE
@@ -956,6 +988,10 @@
     _neutron_setup_interface_driver $Q_L3_CONF_FILE
 
     neutron_plugin_configure_l3_agent
+
+    if [[ $(ip -4 a s dev "$PUBLIC_INTERFACE" | grep -c 'inet') != 0 ]]; then
+        _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True
+    fi
 }
 
 function _configure_neutron_metadata_agent {
@@ -1227,8 +1263,10 @@
         if is_neutron_ovs_base_plugin && [[ "$Q_USE_NAMESPACE" = "True" ]]; then
             local ext_gw_interface=$(_neutron_get_ext_gw_interface)
             local cidr_len=${FLOATING_RANGE#*/}
-            sudo ip addr add $ext_gw_ip/$cidr_len dev $ext_gw_interface
-            sudo ip link set $ext_gw_interface up
+            if [[ $(ip addr show dev $ext_gw_interface | grep -c $ext_gw_ip) == 0 && ( $Q_USE_PROVIDERNET_FOR_PUBLIC == "False" || $Q_USE_PUBLIC_VETH == "True" ) ]]; then
+                sudo ip addr add $ext_gw_ip/$cidr_len dev $ext_gw_interface
+                sudo ip link set $ext_gw_interface up
+            fi
             ROUTER_GW_IP=`neutron port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F '"' -v subnet_id=$PUB_SUBNET_ID '$4 == subnet_id { print $8; }'`
             die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP"
             sudo route add -net $FIXED_RANGE gw $ROUTER_GW_IP
diff --git a/lib/neutron_plugins/README.md b/lib/neutron_plugins/README.md
index 7192a05..4b220d3 100644
--- a/lib/neutron_plugins/README.md
+++ b/lib/neutron_plugins/README.md
@@ -13,7 +13,7 @@
 
 functions
 ---------
-``lib/neutron`` calls the following functions when the ``$Q_PLUGIN`` is enabled
+``lib/neutron-legacy`` calls the following functions when the ``$Q_PLUGIN`` is enabled
 
 * ``neutron_plugin_create_nova_conf`` :
   set ``NOVA_VIF_DRIVER`` and optionally set options in nova_conf
diff --git a/lib/neutron_thirdparty/README.md b/lib/neutron_thirdparty/README.md
index 5655e0b..905ae77 100644
--- a/lib/neutron_thirdparty/README.md
+++ b/lib/neutron_thirdparty/README.md
@@ -10,7 +10,7 @@
 
 functions
 ---------
-``lib/neutron`` calls the following functions when the ``<third_party>`` is enabled
+``lib/neutron-legacy`` calls the following functions when the ``<third_party>`` is enabled
 
 functions to be implemented
 * ``configure_<third_party>``:
diff --git a/lib/nova b/lib/nova
index 502bb35..8e1b2f7 100644
--- a/lib/nova
+++ b/lib/nova
@@ -32,9 +32,16 @@
 
 # Set up default directories
 GITDIR["python-novaclient"]=$DEST/python-novaclient
-
-
 NOVA_DIR=$DEST/nova
+
+# Nova virtual environment
+if [[ ${USE_VENV} = True ]]; then
+    PROJECT_VENV["nova"]=${NOVA_DIR}.venv
+    NOVA_BIN_DIR=${PROJECT_VENV["nova"]}/bin
+else
+    NOVA_BIN_DIR=$(get_python_exec_prefix)
+fi
+
 NOVA_STATE_PATH=${NOVA_STATE_PATH:=$DATA_DIR/nova}
 # INSTANCES_PATH is the previous name for this
 NOVA_INSTANCES_PATH=${NOVA_INSTANCES_PATH:=${INSTANCES_PATH:=$NOVA_STATE_PATH/instances}}
@@ -69,16 +76,6 @@
 EC2_SERVICE_PORT=${EC2_SERVICE_PORT:-8773}
 EC2_SERVICE_PORT_INT=${EC2_SERVICE_PORT_INT:-18773}
 
-# Support entry points installation of console scripts
-if [[ -d $NOVA_DIR/bin ]]; then
-    NOVA_BIN_DIR=$NOVA_DIR/bin
-else
-    NOVA_BIN_DIR=$(get_python_exec_prefix)
-fi
-
-# Set the paths of certain binaries
-NOVA_ROOTWRAP=$(get_rootwrap_location nova)
-
 # Option to enable/disable config drive
 # NOTE: Set FORCE_CONFIG_DRIVE="False" to turn OFF config drive
 FORCE_CONFIG_DRIVE=${FORCE_CONFIG_DRIVE:-"True"}
@@ -225,9 +222,11 @@
     #fi
 }
 
+# Deploy new rootwrap filters files and configure sudo
 # configure_nova_rootwrap() - configure Nova's rootwrap
 function configure_nova_rootwrap {
-    # Deploy new rootwrap filters files (owned by root).
+    nova_rootwrap=$NOVA_BIN_DIR/nova-rootwrap
+
     # Wipe any existing rootwrap.d files first
     if [[ -d $NOVA_CONF_DIR/rootwrap.d ]]; then
         sudo rm -rf $NOVA_CONF_DIR/rootwrap.d
@@ -242,14 +241,21 @@
     sudo sed -e "s:^filters_path=.*$:filters_path=$NOVA_CONF_DIR/rootwrap.d:" -i $NOVA_CONF_DIR/rootwrap.conf
 
     # Specify rootwrap.conf as first parameter to nova-rootwrap
-    local rootwrap_sudoer_cmd="$NOVA_ROOTWRAP $NOVA_CONF_DIR/rootwrap.conf *"
+    local rootwrap_sudoer_cmd="$nova_rootwrap $NOVA_CONF_DIR/rootwrap.conf *"
 
     # Set up the rootwrap sudoers for nova
     local tempfile=`mktemp`
-    echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudoer_cmd" >$tempfile
+    echo "Defaults:$STACK_USER secure_path=$NOVA_BIN_DIR:/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >$tempfile
+    echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudoer_cmd" >>$tempfile
     chmod 0440 $tempfile
     sudo chown root:root $tempfile
     sudo mv $tempfile /etc/sudoers.d/nova-rootwrap
+
+    # So rootwrap and PATH are broken beyond belief.  WTF relies on a SECURE operation
+    # to blindly follow PATH???  We learned that was a bad idea in the 80's!
+    # So to fix this in a venv, we must exploit the very hole we want to close by dropping
+    # a copy of the venv rootwrap binary into /usr/local/bin.
+    #sudo cp -p $nova_rootwrap /usr/local/bin
 }
 
 # configure_nova() - Set config files, create data dirs, etc
@@ -696,6 +702,10 @@
         service_protocol="http"
     fi
 
+    # Hack to set the path for rootwrap
+    local old_path=$PATH
+    export PATH=$NOVA_BIN_DIR:$PATH
+
     run_process n-api "$NOVA_BIN_DIR/nova-api"
     echo "Waiting for nova-api to start..."
     if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$SERVICE_HOST:$service_port; then
@@ -707,10 +717,16 @@
         start_tls_proxy '*' $NOVA_SERVICE_PORT $NOVA_SERVICE_HOST $NOVA_SERVICE_PORT_INT &
         start_tls_proxy '*' $EC2_SERVICE_PORT $NOVA_SERVICE_HOST $EC2_SERVICE_PORT_INT &
     fi
+
+    export PATH=$old_path
 }
 
 # start_nova_compute() - Start the compute process
 function start_nova_compute {
+    # Hack to set the path for rootwrap
+    local old_path=$PATH
+    export PATH=$NOVA_BIN_DIR:$PATH
+
     if is_service_enabled n-cell; then
         local compute_cell_conf=$NOVA_CELLS_CONF
     else
@@ -738,10 +754,16 @@
         fi
         run_process n-cpu "$NOVA_BIN_DIR/nova-compute --config-file $compute_cell_conf"
     fi
+
+    export PATH=$old_path
 }
 
 # start_nova() - Start running processes, including screen
 function start_nova_rest {
+    # Hack to set the path for rootwrap
+    local old_path=$PATH
+    export PATH=$NOVA_BIN_DIR:$PATH
+
     local api_cell_conf=$NOVA_CONF
     if is_service_enabled n-cell; then
         local compute_cell_conf=$NOVA_CELLS_CONF
@@ -769,6 +791,8 @@
     # Swift will act as s3 objectstore.
     is_service_enabled swift3 || \
         run_process n-obj "$NOVA_BIN_DIR/nova-objectstore --config-file $api_cell_conf"
+
+    export PATH=$old_path
 }
 
 function start_nova {
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 4d617e8..60707cf 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -21,14 +21,16 @@
 function install_libvirt {
     if is_ubuntu; then
         install_package qemu-kvm
-        install_package libvirt-bin
-        install_package python-libvirt
-        install_package python-guestfs
+        install_package libvirt-bin libvirt-dev
+        pip_install libvirt-python
+        install_package libguestfs0
+        #install_package python-guestfs
+        #pip_install <there-si-no-guestfs-in-pypi>
     elif is_fedora || is_suse; then
         install_package kvm
-        install_package libvirt
-        install_package libvirt-python
-        install_package python-libguestfs
+        install_package libvirt libvirt-devel
+        pip_install libvirt-python
+        #install_package python-libguestfs
     fi
 
     # Restart firewalld after install of libvirt to avoid a problem
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index 0169d73..b9e286d 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -54,9 +54,7 @@
 
 # install_nova_hypervisor() - Install external components
 function install_nova_hypervisor {
-    if ! is_service_enabled neutron; then
-        die $LINENO "Neutron should be enabled for usage of the Ironic Nova driver."
-    elif is_ironic_hardware; then
+    if is_ironic_hardware; then
         return
     fi
     install_libvirt
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 3d4ef76..3033cbe 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -272,9 +272,9 @@
         fi
     elif is_service_enabled rabbit || { [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; }; then
         iniset $file $section rpc_backend "rabbit"
-        iniset $file $section rabbit_hosts $RABBIT_HOST
-        iniset $file $section rabbit_password $RABBIT_PASSWORD
-        iniset $file $section rabbit_userid $RABBIT_USERID
+        iniset $file oslo_messaging_rabbit rabbit_hosts $RABBIT_HOST
+        iniset $file oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
+        iniset $file oslo_messaging_rabbit rabbit_userid $RABBIT_USERID
     fi
 }
 
diff --git a/lib/sahara b/lib/sahara
index a965f55..0651b0a 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -113,12 +113,13 @@
 
     configure_auth_token_middleware $SAHARA_CONF_FILE sahara $SAHARA_AUTH_CACHE_DIR
 
+    iniset_rpc_backend sahara $SAHARA_CONF_FILE DEFAULT
+
     # Set configuration to send notifications
 
     if is_service_enabled ceilometer; then
         iniset $SAHARA_CONF_FILE DEFAULT enable_notifications "true"
         iniset $SAHARA_CONF_FILE DEFAULT notification_driver "messaging"
-        iniset_rpc_backend sahara $SAHARA_CONF_FILE
     fi
 
     iniset $SAHARA_CONF_FILE DEFAULT verbose True
@@ -203,12 +204,16 @@
 # start_sahara() - Start running processes, including screen
 function start_sahara {
     run_process sahara "$SAHARA_BIN_DIR/sahara-all --config-file $SAHARA_CONF_FILE"
+    run_process sahara-api "$SAHARA_BIN_DIR/sahara-api --config-file $SAHARA_CONF_FILE"
+    run_process sahara-eng "$SAHARA_BIN_DIR/sahara-engine --config-file $SAHARA_CONF_FILE"
 }
 
 # stop_sahara() - Stop running processes
 function stop_sahara {
     # Kill the Sahara screen windows
     stop_process sahara
+    stop_process sahara-api
+    stop_process sahara-eng
 }
 
 
diff --git a/lib/stack b/lib/stack
index 9a509d8..11dd87c 100644
--- a/lib/stack
+++ b/lib/stack
@@ -16,13 +16,17 @@
 function stack_install_service {
     local service=$1
     if type install_${service} >/dev/null 2>&1; then
-        if [[ -n ${PROJECT_VENV[$service]:-} ]]; then
+        if [[ ${USE_VENV} = True && -n ${PROJECT_VENV[$service]:-} ]]; then
             rm -rf ${PROJECT_VENV[$service]}
-            source $TOP_DIR/tools/build_venv.sh ${PROJECT_VENV[$service]}
+            source $TOP_DIR/tools/build_venv.sh ${PROJECT_VENV[$service]} ${ADDITIONAL_VENV_PACKAGES//,/ }
             export PIP_VIRTUAL_ENV=${PROJECT_VENV[$service]:-}
+
+            # Install other OpenStack prereqs that might come from source repos
+            install_oslo
+            install_keystonemiddleware
         fi
         install_${service}
-        if [[ -n ${PROJECT_VENV[$service]:-} ]]; then
+        if [[ ${USE_VENV} = True && -n ${PROJECT_VENV[$service]:-} ]]; then
             unset PIP_VIRTUAL_ENV
         fi
     fi
diff --git a/lib/swift b/lib/swift
index af19c68..28ef7de 100644
--- a/lib/swift
+++ b/lib/swift
@@ -64,11 +64,19 @@
     S3_SERVICE_PORT=${S3_SERVICE_PORT:-8080}
 fi
 
-# DevStack will create a loop-back disk formatted as XFS to store the
-# swift data. Set ``SWIFT_LOOPBACK_DISK_SIZE`` to the disk size in
-# kilobytes.
-# Default is 1 gigabyte.
-SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=1G
+if is_service_enabled g-api; then
+    # Minimum Cinder volume size is 1G so if Swift backend for Glance is
+    # only 1G we can not upload volume to image.
+    # Increase Swift disk size up to 2G
+    SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=2G
+else
+    # DevStack will create a loop-back disk formatted as XFS to store the
+    # swift data. Set ``SWIFT_LOOPBACK_DISK_SIZE`` to the disk size in
+    # kilobytes.
+    # Default is 1 gigabyte.
+    SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=1G
+fi
+
 # if tempest enabled the default size is 6 Gigabyte.
 if is_service_enabled tempest; then
     SWIFT_LOOPBACK_DISK_SIZE_DEFAULT=${SWIFT_LOOPBACK_DISK_SIZE:-6G}
diff --git a/lib/tempest b/lib/tempest
index 443915c..e97dfd6 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -175,6 +175,10 @@
 
     password=${ADMIN_PASSWORD:-secrete}
 
+    # Do we want to make a configuration where Tempest has admin on
+    # the cloud. We don't always want to so that we can ensure Tempest
+    # would work on a public cloud.
+    TEMPEST_HAS_ADMIN=$(trueorfalse True TEMPEST_HAS_ADMIN)
     # See files/keystone_data.sh and stack.sh where admin, demo and alt_demo
     # user and tenant are set up...
     ADMIN_USERNAME=${ADMIN_USERNAME:-admin}
@@ -292,11 +296,13 @@
     iniset $TEMPEST_CONFIG identity alt_username $ALT_USERNAME
     iniset $TEMPEST_CONFIG identity alt_password "$password"
     iniset $TEMPEST_CONFIG identity alt_tenant_name $ALT_TENANT_NAME
-    iniset $TEMPEST_CONFIG identity admin_username $ADMIN_USERNAME
-    iniset $TEMPEST_CONFIG identity admin_password "$password"
-    iniset $TEMPEST_CONFIG identity admin_tenant_name $ADMIN_TENANT_NAME
-    iniset $TEMPEST_CONFIG identity admin_tenant_id $ADMIN_TENANT_ID
-    iniset $TEMPEST_CONFIG identity admin_domain_name $ADMIN_DOMAIN_NAME
+    if [[ "$TEMPEST_HAS_ADMIN" == "True" ]]; then
+        iniset $TEMPEST_CONFIG identity admin_username $ADMIN_USERNAME
+        iniset $TEMPEST_CONFIG identity admin_password "$password"
+        iniset $TEMPEST_CONFIG identity admin_tenant_name $ADMIN_TENANT_NAME
+        iniset $TEMPEST_CONFIG identity admin_tenant_id $ADMIN_TENANT_ID
+        iniset $TEMPEST_CONFIG identity admin_domain_name $ADMIN_DOMAIN_NAME
+    fi
     iniset $TEMPEST_CONFIG identity auth_version ${TEMPEST_AUTH_VERSION:-v2}
     if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
         iniset $TEMPEST_CONFIG identity ca_certificates_file $SSL_BUNDLE_FILE
@@ -310,10 +316,11 @@
     fi
 
     # Auth
+    #
+    #
+    TEMPEST_ALLOW_TENANT_ISOLATION=${TEMPEST_ALLOW_TENANT_ISOLATION:-$TEMPEST_HAS_ADMIN}
     iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
-    if [[ "$TEMPEST_AUTH_VERSION" == "v3" ]]; then
-        iniset $TEMPEST_CONFIG auth tempest_roles "Member"
-    fi
+    iniset $TEMPEST_CONFIG auth tempest_roles "Member"
 
     # Compute
     iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
@@ -333,7 +340,7 @@
     # NOTE(mtreinish): This must be done after auth settings are added to the tempest config
     local tmp_cfg_file=$(mktemp)
     cd $TEMPEST_DIR
-    tox -evenv -- verify-tempest-config -uro $tmp_cfg_file
+    tox -revenv -- verify-tempest-config -uro $tmp_cfg_file
 
     local compute_api_extensions=${COMPUTE_API_EXTENSIONS:-"all"}
     if [[ ! -z "$DISABLE_COMPUTE_API_EXTENSIONS" ]]; then
@@ -351,11 +358,6 @@
     # TODO(mriedem): Remove the preserve_ports flag when Juno is end of life.
     iniset $TEMPEST_CONFIG compute-feature-enabled preserve_ports True
 
-    # Compute admin
-    iniset $TEMPEST_CONFIG "compute-admin" username $ADMIN_USERNAME
-    iniset $TEMPEST_CONFIG "compute-admin" password "$password"
-    iniset $TEMPEST_CONFIG "compute-admin" tenant_name $ADMIN_TENANT_NAME
-
     # Network
     iniset $TEMPEST_CONFIG network api_version 2.0
     iniset $TEMPEST_CONFIG network tenant_networks_reachable "$tenant_networks_reachable"
diff --git a/stack.sh b/stack.sh
index 9d62303..090d527 100755
--- a/stack.sh
+++ b/stack.sh
@@ -89,6 +89,9 @@
     exit 1
 fi
 
+# Print the kernel version
+uname -a
+
 # Prepare the environment
 # -----------------------
 
@@ -507,6 +510,10 @@
 # Configure Projects
 # ==================
 
+# Plugin Phase 0: override_defaults - allow pluggins to override
+# defaults before other services are run
+run_phase override_defaults
+
 # Import apache functions
 source $TOP_DIR/lib/apache
 
@@ -525,7 +532,7 @@
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
 source $TOP_DIR/lib/dstat
 
@@ -706,6 +713,7 @@
 
 if is_service_enabled $DATABASE_BACKENDS; then
     install_database
+    install_database_python
 fi
 
 if is_service_enabled neutron; then
diff --git a/stackrc b/stackrc
index a13f82a..143298c 100644
--- a/stackrc
+++ b/stackrc
@@ -104,6 +104,16 @@
     source $RC_DIR/.localrc.auto
 fi
 
+# Enable use of Python virtual environments.  Individual project use of
+# venvs are controlled by the PROJECT_VENV array; every project with
+# an entry in the array will be installed into the named venv.
+# By default this will put each project into its own venv.
+USE_VENV=$(trueorfalse False USE_VENV)
+
+# Add packages that need to be installed into a venv but are not in any
+# requirmenets files here, in a comma-separated list
+ADDITIONAL_VENV_PACKAGES=${ADITIONAL_VENV_PACKAGES:-""}
+
 # Configure wheel cache location
 export WHEELHOUSE=${WHEELHOUSE:-$DEST/.wheelhouse}
 export PIP_WHEEL_DIR=${PIP_WHEEL_DIR:-$WHEELHOUSE}
@@ -560,18 +570,6 @@
         IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz"};;
 esac
 
-# Use 64bit fedora image if heat is enabled
-if [[ "$ENABLED_SERVICES" =~ 'h-api' ]]; then
-    case "$VIRT_DRIVER" in
-        libvirt|ironic)
-            HEAT_CFN_IMAGE_URL=${HEAT_CFN_IMAGE_URL:-"https://download.fedoraproject.org/pub/alt/openstack/20/x86_64/Fedora-x86_64-20-20140618-sda.qcow2"}
-            IMAGE_URLS+=",$HEAT_CFN_IMAGE_URL"
-            ;;
-        *)
-            ;;
-    esac
-fi
-
 # Trove needs a custom image for its work
 if [[ "$ENABLED_SERVICES" =~ 'tr-api' ]]; then
     case "$VIRT_DRIVER" in
@@ -584,17 +582,6 @@
     esac
 fi
 
-# Staging Area for New Images, have them here for at least 24hrs for nodepool
-# to cache them otherwise the failure rates in the gate are too high
-PRECACHE_IMAGES=$(trueorfalse False PRECACHE_IMAGES)
-if [[ "$PRECACHE_IMAGES" == "True" ]]; then
-    # staging in update for nodepool
-    IMAGE_URL="https://download.fedoraproject.org/pub/alt/openstack/20/x86_64/Fedora-x86_64-20-20140618-sda.qcow2"
-    if ! [[ "$IMAGE_URLS"  =~ "$IMAGE_URL" ]]; then
-        IMAGE_URLS+=",$IMAGE_URL"
-    fi
-fi
-
 # 10Gb default volume backing file size
 VOLUME_BACKING_FILE_SIZE=${VOLUME_BACKING_FILE_SIZE:-10250M}
 
diff --git a/unstack.sh b/unstack.sh
index fdd63fb..c45af74 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -45,6 +45,10 @@
 # Configure Projects
 # ==================
 
+# Plugin Phase 0: override_defaults - allow pluggins to override
+# defaults before other services are run
+run_phase override_defaults
+
 # Import apache functions
 source $TOP_DIR/lib/apache
 
@@ -63,7 +67,7 @@
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
-source $TOP_DIR/lib/neutron
+source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
 source $TOP_DIR/lib/dstat