Merge "put mysql on a memory diet"
diff --git a/doc/source/guides/multinode-lab.rst b/doc/source/guides/multinode-lab.rst
index dfc9936..1b7f4cd 100644
--- a/doc/source/guides/multinode-lab.rst
+++ b/doc/source/guides/multinode-lab.rst
@@ -176,7 +176,7 @@
     MYSQL_HOST=$SERVICE_HOST
     RABBIT_HOST=$SERVICE_HOST
     GLANCE_HOSTPORT=$SERVICE_HOST:9292
-    ENABLED_SERVICES=n-cpu,n-net,n-api-meta,c-vol
+    ENABLED_SERVICES=n-cpu,q-agt,n-api-meta,c-vol
     NOVA_VNC_ENABLED=True
     NOVNCPROXY_URL="http://$SERVICE_HOST:6080/vnc_auto.html"
     VNCSERVER_LISTEN=$HOST_IP
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 17da67b..266ab0d 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -108,7 +108,6 @@
 networking-mlnx                        `git://git.openstack.org/openstack/networking-mlnx <https://git.openstack.org/cgit/openstack/networking-mlnx>`__
 networking-nec                         `git://git.openstack.org/openstack/networking-nec <https://git.openstack.org/cgit/openstack/networking-nec>`__
 networking-odl                         `git://git.openstack.org/openstack/networking-odl <https://git.openstack.org/cgit/openstack/networking-odl>`__
-networking-ofagent                     `git://git.openstack.org/openstack/networking-ofagent <https://git.openstack.org/cgit/openstack/networking-ofagent>`__
 networking-onos                        `git://git.openstack.org/openstack/networking-onos <https://git.openstack.org/cgit/openstack/networking-onos>`__
 networking-ovn                         `git://git.openstack.org/openstack/networking-ovn <https://git.openstack.org/cgit/openstack/networking-ovn>`__
 networking-ovs-dpdk                    `git://git.openstack.org/openstack/networking-ovs-dpdk <https://git.openstack.org/cgit/openstack/networking-ovs-dpdk>`__
@@ -150,6 +149,7 @@
 vitrage                                `git://git.openstack.org/openstack/vitrage <https://git.openstack.org/cgit/openstack/vitrage>`__
 vitrage-dashboard                      `git://git.openstack.org/openstack/vitrage-dashboard <https://git.openstack.org/cgit/openstack/vitrage-dashboard>`__
 vmware-nsx                             `git://git.openstack.org/openstack/vmware-nsx <https://git.openstack.org/cgit/openstack/vmware-nsx>`__
+vmware-vspc                            `git://git.openstack.org/openstack/vmware-vspc <https://git.openstack.org/cgit/openstack/vmware-vspc>`__
 watcher                                `git://git.openstack.org/openstack/watcher <https://git.openstack.org/cgit/openstack/watcher>`__
 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>`__
diff --git a/files/debs/neutron b/files/debs/neutron
index 2307fa5..e30f678 100644
--- a/files/debs/neutron
+++ b/files/debs/neutron
@@ -2,6 +2,7 @@
 dnsmasq-base
 dnsmasq-utils # for dhcp_release only available in dist:precise
 ebtables
+haproxy # to serve as metadata proxy inside router/dhcp namespaces
 iptables
 iputils-arping
 iputils-ping
diff --git a/files/rpms-suse/neutron b/files/rpms-suse/neutron
index e9abc6e..d1cc73f 100644
--- a/files/rpms-suse/neutron
+++ b/files/rpms-suse/neutron
@@ -2,6 +2,7 @@
 dnsmasq
 dnsmasq-utils # dist:opensuse-12.3,opensuse-13.1
 ebtables
+haproxy # to serve as metadata proxy inside router/dhcp namespaces
 iptables
 iputils
 mariadb # NOPRIME
diff --git a/files/rpms/neutron b/files/rpms/neutron
index 2e49a0c..a4e029a 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -2,6 +2,7 @@
 dnsmasq # for q-dhcp
 dnsmasq-utils # for dhcp_release
 ebtables
+haproxy # to serve as metadata proxy inside router/dhcp namespaces
 iptables
 iputils
 mysql-devel
diff --git a/files/rpms/nova b/files/rpms/nova
index 45f1c94..a368c55 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -9,10 +9,6 @@
 iputils
 kernel-modules # dist:f23,f24,f25
 kpartx
-kvm # NOPRIME
-libvirt-bin # NOPRIME
-libvirt-devel # NOPRIME
-libvirt-python # NOPRIME
 libxml2-python
 m2crypto
 mysql-devel
@@ -21,7 +17,6 @@
 numpy # needed by websockify for spice console
 parted
 polkit
-qemu-kvm # NOPRIME
 rabbitmq-server # NOPRIME
 sqlite
 sudo
diff --git a/functions b/functions
index 89ee367..1aa7517 100644
--- a/functions
+++ b/functions
@@ -12,7 +12,7 @@
 
 # ensure we don't re-source this in the same environment
 [[ -z "$_DEVSTACK_FUNCTIONS" ]] || return 0
-declare -r _DEVSTACK_FUNCTIONS=1
+declare -r -g _DEVSTACK_FUNCTIONS=1
 
 # Include the common functions
 FUNC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
@@ -664,6 +664,16 @@
 }
 
 
+# running_in_container - Returns true otherwise false
+function running_in_container {
+    if grep -q lxc /proc/1/cgroup; then
+        return 0
+    fi
+
+    return 1
+}
+
+
 # enable_kernel_bridge_firewall - Enable kernel support for bridge firewalling
 function enable_kernel_bridge_firewall {
     # Load bridge module. This module provides access to firewall for bridged
diff --git a/functions-common b/functions-common
index 0d1b01f..a86cfd8 100644
--- a/functions-common
+++ b/functions-common
@@ -37,12 +37,12 @@
 
 # ensure we don't re-source this in the same environment
 [[ -z "$_DEVSTACK_FUNCTIONS_COMMON" ]] || return 0
-declare -r _DEVSTACK_FUNCTIONS_COMMON=1
+declare -r -g _DEVSTACK_FUNCTIONS_COMMON=1
 
 # Global Config Variables
-declare -A GITREPO
-declare -A GITBRANCH
-declare -A GITDIR
+declare -A -g GITREPO
+declare -A -g GITBRANCH
+declare -A -g GITDIR
 
 TRACK_DEPENDS=${TRACK_DEPENDS:-False}
 
@@ -306,7 +306,7 @@
 # ``os_PACKAGE`` - package type: ``deb`` or ``rpm``
 # ``os_CODENAME`` - vendor's codename for release: ``xenial``
 
-declare os_VENDOR os_RELEASE os_PACKAGE os_CODENAME
+declare -g os_VENDOR os_RELEASE os_PACKAGE os_CODENAME
 
 # Make a *best effort* attempt to install lsb_release packages for the
 # user if not available.  Note can't use generic install_package*
@@ -361,7 +361,7 @@
 
 # Translate the OS version values into common nomenclature
 # Sets global ``DISTRO`` from the ``os_*`` values
-declare DISTRO
+declare -g DISTRO
 
 function GetDistro {
     GetOSVersion
@@ -1556,7 +1556,7 @@
     # Append the process to the screen rc file
     screen_rc "$name" "$command"
 
-    screen -S $SCREEN_NAME -p $name -X stuff "$command & echo \$! >$SERVICE_DIR/$SCREEN_NAME/${name}.pid; fg || echo \"$name failed to start\" | tee \"$SERVICE_DIR/$SCREEN_NAME/${name}.failure\"$NL"
+    screen -S $SCREEN_NAME -p $name -X stuff "$command & echo \$! >$SERVICE_DIR/$SCREEN_NAME/${name}.pid; fg || echo \"$name failed to start. Exit code: \$?\" | tee \"$SERVICE_DIR/$SCREEN_NAME/${name}.failure\"$NL"
 }
 
 # Screen rc file builder
@@ -2376,9 +2376,9 @@
 # Resolution is only in whole seconds, so should be used for long
 # running activities.
 
-declare -A _TIME_TOTAL
-declare -A _TIME_START
-declare -r _TIME_BEGIN=$(date +%s)
+declare -A -g _TIME_TOTAL
+declare -A -g _TIME_START
+declare -r -g _TIME_BEGIN=$(date +%s)
 
 # time_start $name
 #
diff --git a/inc/python b/inc/python
index 5afc07f..a4819c2 100644
--- a/inc/python
+++ b/inc/python
@@ -19,7 +19,7 @@
 
 # PROJECT_VENV contains the name of the virtual environment for each
 # project.  A null value installs to the system Python directories.
-declare -A PROJECT_VENV
+declare -A -g PROJECT_VENV
 
 
 # Python Functions
@@ -111,6 +111,111 @@
     echo $classifier
 }
 
+# python3_enabled_for() checks if the service(s) specified as arguments are
+# enabled by the user in ``ENABLED_PYTHON3_PACKAGES``.
+#
+# Multiple services specified as arguments are ``OR``'ed together; the test
+# is a short-circuit boolean, i.e it returns on the first match.
+#
+# Uses global ``ENABLED_PYTHON3_PACKAGES``
+# python3_enabled_for dir [dir ...]
+function python3_enabled_for {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
+    local enabled=1
+    local dirs=$@
+    local dir
+    for dir in ${dirs}; do
+        [[ ,${ENABLED_PYTHON3_PACKAGES}, =~ ,${dir}, ]] && enabled=0
+    done
+
+    $xtrace
+    return $enabled
+}
+
+# python3_disabled_for() checks if the service(s) specified as arguments are
+# disabled by the user in ``DISABLED_PYTHON3_PACKAGES``.
+#
+# Multiple services specified as arguments are ``OR``'ed together; the test
+# is a short-circuit boolean, i.e it returns on the first match.
+#
+# Uses global ``DISABLED_PYTHON3_PACKAGES``
+# python3_disabled_for dir [dir ...]
+function python3_disabled_for {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
+    local enabled=1
+    local dirs=$@
+    local dir
+    for dir in ${dirs}; do
+        [[ ,${DISABLED_PYTHON3_PACKAGES}, =~ ,${dir}, ]] && enabled=0
+    done
+
+    $xtrace
+    return $enabled
+}
+
+# enable_python3_package() adds the repositories passed as argument to the
+# ``ENABLED_PYTHON3_PACKAGES`` list, if they are not already present.
+#
+# For example:
+#   enable_python3_package nova
+#
+# Uses global ``ENABLED_PYTHON3_PACKAGES``
+# enable_python3_package dir [dir ...]
+function enable_python3_package {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
+    local tmpsvcs="${ENABLED_PYTHON3_PACKAGES}"
+    local python3
+    for dir in $@; do
+        if [[ ,${DISABLED_PYTHON3_PACKAGES}, =~ ,${dir}, ]]; then
+            warn $LINENO "Attempt to enable_python3_package ${dir} when it has been disabled"
+            continue
+        fi
+        if ! python3_enabled_for $dir; then
+            tmpsvcs+=",$dir"
+        fi
+    done
+    ENABLED_PYTHON3_PACKAGES=$(_cleanup_service_list "$tmpsvcs")
+
+    $xtrace
+}
+
+# disable_python3_package() prepares the services passed as argument to be
+# removed from the ``ENABLED_PYTHON3_PACKAGES`` list, if they are present.
+#
+# For example:
+#   disable_python3_package swift
+#
+# Uses globals ``ENABLED_PYTHON3_PACKAGES`` and ``DISABLED_PYTHON3_PACKAGES``
+# disable_python3_package dir [dir ...]
+function disable_python3_package {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+
+    local disabled_svcs="${DISABLED_PYTHON3_PACKAGES}"
+    local enabled_svcs=",${ENABLED_PYTHON3_PACKAGES},"
+    local dir
+    for dir in $@; do
+        disabled_svcs+=",$dir"
+        if python3_enabled_for $dir; then
+            enabled_svcs=${enabled_svcs//,$dir,/,}
+        fi
+    done
+    DISABLED_PYTHON3_PACKAGES=$(_cleanup_service_list "$disabled_svcs")
+    ENABLED_PYTHON3_PACKAGES=$(_cleanup_service_list "$enabled_svcs")
+
+    $xtrace
+}
+
 # Wrapper for ``pip install`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
 # ``PIP_UPGRADE``, ``TRACK_DEPENDS``, ``*_proxy``,
@@ -163,16 +268,16 @@
                 # support for python3 in progress, but don't claim support
                 # in their classifier
                 echo "Check python version for : $package_dir"
-                if [[ ${package_dir##*/} == "nova" || ${package_dir##*/} == "glance" || \
-                        ${package_dir##*/} == "cinder" || ${package_dir##*/} == "swift" || \
-                        ${package_dir##*/} == "uwsgi" ]]; then
-                    echo "Using $PYTHON3_VERSION version to install $package_dir"
+                if python3_disabled_for ${package_dir##*/}; then
+                    echo "Explicitly using $PYTHON2_VERSION version to install $package_dir based on DISABLED_PYTHON3_PACKAGES"
+                elif python3_enabled_for ${package_dir##*/}; then
+                    echo "Explicitly using $PYTHON3_VERSION version to install $package_dir based on ENABLED_PYTHON3_PACKAGES"
                     sudo_pip="$sudo_pip LC_ALL=en_US.UTF-8"
                     cmd_pip=$(get_pip_command $PYTHON3_VERSION)
                 elif [[ -d "$package_dir" ]]; then
                     python_versions=$(get_python_versions_for_package $package_dir)
                     if [[ $python_versions =~ $PYTHON3_VERSION ]]; then
-                        echo "Using $PYTHON3_VERSION version to install $package_dir"
+                        echo "Automatically using $PYTHON3_VERSION version to install $package_dir based on classifiers"
                         sudo_pip="$sudo_pip LC_ALL=en_US.UTF-8"
                         cmd_pip=$(get_pip_command $PYTHON3_VERSION)
                     else
@@ -181,7 +286,7 @@
                         # a warning.
                         python3_classifier=$(check_python3_support_for_package_local $package_dir)
                         if [[ ! -z "$python3_classifier" ]]; then
-                            echo "Using $PYTHON3_VERSION version to install $package_dir"
+                            echo "Automatically using $PYTHON3_VERSION version to install $package_dir based on local package settings"
                             sudo_pip="$sudo_pip LC_ALL=en_US.UTF-8"
                             cmd_pip=$(get_pip_command $PYTHON3_VERSION)
                         fi
@@ -191,7 +296,7 @@
                     package=$(echo $package_dir | grep -o '^[.a-zA-Z0-9_-]*')
                     python3_classifier=$(check_python3_support_for_package_remote $package)
                     if [[ ! -z "$python3_classifier" ]]; then
-                        echo "Using $PYTHON3_VERSION version to install $package"
+                        echo "Automatically using $PYTHON3_VERSION version to install $package based on remote package settings"
                         sudo_pip="$sudo_pip LC_ALL=en_US.UTF-8"
                         cmd_pip=$(get_pip_command $PYTHON3_VERSION)
                     fi
@@ -308,6 +413,16 @@
 function setup_dev_lib {
     local name=$1
     local dir=${GITDIR[$name]}
+    if python3_enabled; then
+        # Turn off Python 3 mode and install the package again,
+        # forcing a Python 2 installation. This ensures that all libs
+        # being used for development are installed under both versions
+        # of Python.
+        echo "Installing $name again without Python 3 enabled"
+        USE_PYTHON3=False
+        setup_develop $dir
+        USE_PYTHON3=True
+    fi
     setup_develop $dir
 }
 
diff --git a/lib/cinder b/lib/cinder
index 767fd00..c17cea0 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -315,7 +315,7 @@
     fi
 
     if is_service_enabled ceilometer; then
-        iniset $CINDER_CONF oslo_messaging_notifications driver "messaging"
+        iniset $CINDER_CONF oslo_messaging_notifications driver "messagingv2"
     fi
 
     if is_service_enabled tls-proxy; then
diff --git a/lib/cinder_backends/fake b/lib/cinder_backends/fake
new file mode 100644
index 0000000..4749ace
--- /dev/null
+++ b/lib/cinder_backends/fake
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# lib/cinder_backends/fake
+# Configure the Fake backend
+
+# Enable with:
+#
+#   CINDER_ENABLED_BACKENDS+=,fake:fake
+
+# Dependencies:
+#
+# - ``functions`` file
+# - ``cinder`` configurations
+
+# CINDER_CONF
+
+# clean_cinder_backend_fake - called from clean_cinder()
+# configure_cinder_backend_fake - called from configure_cinder()
+# init_cinder_backend_fake - called from init_cinder()
+
+
+# Save trace setting
+_XTRACE_CINDER_FAKE=$(set +o | grep xtrace)
+set +o xtrace
+
+
+function cleanup_cinder_backend_fake {
+    local be_name=$1
+}
+
+function configure_cinder_backend_fake {
+    local be_name=$1
+
+    iniset $CINDER_CONF $be_name volume_backend_name $be_name
+    iniset $CINDER_CONF $be_name volume_driver "cinder.tests.fake_driver.FakeLoggingVolumeDriver"
+
+}
+
+function init_cinder_backend_fake {
+    local be_name=$1
+}
+
+# Restore xtrace
+$_XTRACE_CINDER_FAKE
+
+# mode: shell-script
+# End:
diff --git a/lib/cinder_backends/fake_gate b/lib/cinder_backends/fake_gate
new file mode 100644
index 0000000..6b1f848
--- /dev/null
+++ b/lib/cinder_backends/fake_gate
@@ -0,0 +1,74 @@
+#!/bin/bash
+#
+# lib/cinder_backends/lvm
+# Configure the LVM backend
+
+# Enable with:
+#
+#   CINDER_ENABLED_BACKENDS+=,fake_gate:lvmname
+
+# Dependencies:
+#
+# - ``functions`` file
+# - ``cinder`` configurations
+
+# CINDER_CONF
+# DATA_DIR
+# VOLUME_GROUP_NAME
+
+# clean_cinder_backend_lvm - called from clean_cinder()
+# configure_cinder_backend_lvm - called from configure_cinder()
+# init_cinder_backend_lvm - called from init_cinder()
+
+
+# Save trace setting
+_XTRACE_CINDER_LVM=$(set +o | grep xtrace)
+set +o xtrace
+
+
+# TODO: resurrect backing device...need to know how to set values
+#VOLUME_BACKING_DEVICE=${VOLUME_BACKING_DEVICE:-}
+
+# Entry Points
+# ------------
+
+# cleanup_cinder_backend_lvm - Delete volume group and remove backing file
+# cleanup_cinder_backend_lvm $be_name
+function cleanup_cinder_backend_lvm {
+    local be_name=$1
+
+    # Campsite rule: leave behind a volume group at least as clean as we found it
+    clean_lvm_volume_group $VOLUME_GROUP_NAME-$be_name
+    clean_lvm_filter
+}
+
+# configure_cinder_backend_lvm - Set config files, create data dirs, etc
+# configure_cinder_backend_lvm $be_name
+function configure_cinder_backend_lvm {
+    local be_name=$1
+
+    iniset $CINDER_CONF $be_name volume_backend_name $be_name
+    iniset $CINDER_CONF $be_name volume_driver "cinder.tests.fake_driver.FakeGateDriver"
+    iniset $CINDER_CONF $be_name volume_group $VOLUME_GROUP_NAME-$be_name
+    iniset $CINDER_CONF $be_name iscsi_helper "$CINDER_ISCSI_HELPER"
+    iniset $CINDER_CONF $be_name lvm_type "$CINDER_LVM_TYPE"
+
+    if [[ "$CINDER_VOLUME_CLEAR" == "non" ]]; then
+        iniset $CINDER_CONF $be_name volume_clear none
+    fi
+}
+
+# init_cinder_backend_lvm - Initialize volume group
+# init_cinder_backend_lvm $be_name
+function init_cinder_backend_lvm {
+    local be_name=$1
+
+    # Start with a clean volume group
+    init_lvm_volume_group $VOLUME_GROUP_NAME-$be_name $VOLUME_BACKING_FILE_SIZE
+}
+
+# Restore xtrace
+$_XTRACE_CINDER_LVM
+
+# mode: shell-script
+# End:
diff --git a/lib/glance b/lib/glance
index 58f1def..6125f45 100644
--- a/lib/glance
+++ b/lib/glance
@@ -57,7 +57,7 @@
 GLANCE_SWIFT_STORE_CONF=$GLANCE_CONF_DIR/glance-swift-store.conf
 GLANCE_GLARE_CONF=$GLANCE_CONF_DIR/glance-glare.conf
 GLANCE_GLARE_PASTE_INI=$GLANCE_CONF_DIR/glance-glare-paste.ini
-GLANCE_V1_ENABLED=${GLANCE_V1_ENABLED:-True}
+GLANCE_V1_ENABLED=${GLANCE_V1_ENABLED:-False}
 
 if is_ssl_enabled_service "glance" || is_service_enabled tls-proxy; then
     GLANCE_SERVICE_PROTOCOL="https"
@@ -112,7 +112,7 @@
     iniset $GLANCE_REGISTRY_CONF DEFAULT workers "$API_WORKERS"
     iniset $GLANCE_REGISTRY_CONF paste_deploy flavor keystone
     configure_auth_token_middleware $GLANCE_REGISTRY_CONF glance $GLANCE_AUTH_CACHE_DIR/registry
-    iniset $GLANCE_REGISTRY_CONF oslo_messaging_notifications driver messaging
+    iniset $GLANCE_REGISTRY_CONF oslo_messaging_notifications driver messagingv2
     iniset_rpc_backend glance $GLANCE_REGISTRY_CONF
     iniset $GLANCE_REGISTRY_CONF DEFAULT graceful_shutdown_timeout "$SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT"
 
@@ -125,7 +125,7 @@
     iniset $GLANCE_API_CONF DEFAULT image_cache_dir $GLANCE_CACHE_DIR/
     iniset $GLANCE_API_CONF paste_deploy flavor keystone+cachemanagement
     configure_auth_token_middleware $GLANCE_API_CONF glance $GLANCE_AUTH_CACHE_DIR/api
-    iniset $GLANCE_API_CONF oslo_messaging_notifications driver messaging
+    iniset $GLANCE_API_CONF oslo_messaging_notifications driver messagingv2
     iniset_rpc_backend glance $GLANCE_API_CONF
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
         iniset $GLANCE_API_CONF DEFAULT container_formats "ami,ari,aki,bare,ovf,tgz"
diff --git a/lib/neutron b/lib/neutron
index 19568ea..9a2a75a 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -52,9 +52,13 @@
 NEUTRON_CORE_PLUGIN_CONF_PATH=$NEUTRON_CONF_DIR/plugins/$NEUTRON_CORE_PLUGIN
 NEUTRON_CORE_PLUGIN_CONF=$NEUTRON_CORE_PLUGIN_CONF_PATH/$NEUTRON_CORE_PLUGIN_CONF_FILENAME
 
+NEUTRON_METERING_AGENT_CONF_FILENAME=${NEUTRON_METERING_AGENT_CONF_FILENAME:-metering_agent.ini}
+NEUTRON_METERING_AGENT_CONF=$NEUTRON_CONF_DIR/$NEUTRON_METERING_AGENT_CONF_FILENAME
+
 NEUTRON_AGENT_BINARY=${NEUTRON_AGENT_BINARY:-neutron-$NEUTRON_AGENT-agent}
 NEUTRON_L3_BINARY=${NEUTRON_L3_BINARY:-neutron-l3-agent}
 NEUTRON_META_BINARY=${NEUTRON_META_BINARY:-neutron-metadata-agent}
+NEUTRON_METERING_BINARY=${NEUTRON_METERING_BINARY:-neutron-metering-agent}
 
 # Public facing bits
 if is_ssl_enabled_service "neutron" || is_service_enabled tls-proxy; then
@@ -70,11 +74,16 @@
 NEUTRON_ROOTWRAP_CONF_FILE=$NEUTRON_CONF_DIR/rootwrap.conf
 NEUTRON_ROOTWRAP_DAEMON_CMD="sudo $NEUTRON_ROOTWRAP-daemon $NEUTRON_ROOTWRAP_CONF_FILE"
 
-# Add all enabled config files to a single config arg
-NEUTRON_CONFIG_ARG=${NEUTRON_CONFIG_ARG:-""}
+# This is needed because _neutron_ovs_base_configure_l3_agent will set
+# external_network_bridge
+Q_USE_PROVIDERNET_FOR_PUBLIC=${Q_USE_PROVIDERNET_FOR_PUBLIC:-True}
+# This is needed because _neutron_ovs_base_configure_l3_agent uses it to create
+# an external network bridge
+PUBLIC_BRIDGE=${PUBLIC_BRIDGE:-br-ex}
+PUBLIC_BRIDGE_MTU=${PUBLIC_BRIDGE_MTU:-1500}
 
 # Additional neutron api config files
-declare -a _NEUTRON_SERVER_EXTRA_CONF_FILES_ABS
+declare -a -g _NEUTRON_SERVER_EXTRA_CONF_FILES_ABS
 
 # Functions
 # ---------
@@ -153,15 +162,7 @@
 
         iniset $NEUTRON_CONF DEFAULT auth_strategy $NEUTRON_AUTH_STRATEGY
         configure_auth_token_middleware $NEUTRON_CONF neutron $NEUTRON_AUTH_CACHE_DIR keystone_authtoken
-
-        iniset $NEUTRON_CONF nova auth_type password
-        iniset $NEUTRON_CONF nova auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
-        iniset $NEUTRON_CONF nova username nova
-        iniset $NEUTRON_CONF nova password $SERVICE_PASSWORD
-        iniset $NEUTRON_CONF nova user_domain_id default
-        iniset $NEUTRON_CONF nova project_name $SERVICE_TENANT_NAME
-        iniset $NEUTRON_CONF nova project_domain_id default
-        iniset $NEUTRON_CONF nova region_name $REGION_NAME
+        configure_auth_token_middleware $NEUTRON_CONF nova $NEUTRON_AUTH_CACHE_DIR nova
 
         # Configure VXLAN
         # TODO(sc68cal) not hardcode?
@@ -188,7 +189,9 @@
             iniset $NEUTRON_CORE_PLUGIN_CONF ovs local_ip $HOST_IP
         fi
 
-        enable_kernel_bridge_firewall
+        if ! running_in_container; then
+            enable_kernel_bridge_firewall
+        fi
     fi
 
     # DHCP Agent
@@ -240,10 +243,6 @@
         iniset $NEUTRON_CONF DEFAULT bind_port "$NEUTRON_SERVICE_PORT_INT"
     fi
 
-    if is_ssl_enabled_service "nova"; then
-        iniset $NEUTRON_CONF nova cafile $SSL_BUNDLE_FILE
-    fi
-
     if is_ssl_enabled_service "neutron"; then
         ensure_certificates NEUTRON
 
@@ -254,9 +253,7 @@
 
     # Metering
     if is_service_enabled neutron-metering; then
-        source $TOP_DIR/lib/neutron_plugins/services/metering
-        neutron_agent_metering_configure_common
-        neutron_agent_metering_configure_agent
+        cp $NEUTRON_DIR/etc/metering_agent.ini.sample $NEUTRON_METERING_AGENT_CONF
         neutron_service_plugin_class_add metering
     fi
 }
@@ -295,7 +292,7 @@
 function configure_neutron_nova_new {
     iniset $NOVA_CONF DEFAULT use_neutron True
     iniset $NOVA_CONF neutron auth_type "password"
-    iniset $NOVA_CONF neutron auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+    iniset $NOVA_CONF neutron auth_url "$KEYSTONE_SERVICE_URI/v3"
     iniset $NOVA_CONF neutron username neutron
     iniset $NOVA_CONF neutron password "$SERVICE_PASSWORD"
     iniset $NOVA_CONF neutron user_domain_name "Default"
@@ -347,7 +344,7 @@
     recreate_database neutron
 
     # Run Neutron db migrations
-    $NEUTRON_BIN_DIR/neutron-db-manage $NEUTRON_CONFIG_ARG upgrade heads
+    $NEUTRON_BIN_DIR/neutron-db-manage upgrade heads
 
     create_neutron_cache_dir
 }
@@ -395,9 +392,9 @@
         service_protocol="http"
     fi
 
-    local opts = ""
-    opts+="--config-file $NEUTRON_CONF"
-    opts+="--config-file $NEUTRON_CORE_PLUGIN_CONF"
+    local opts=""
+    opts+=" --config-file $NEUTRON_CONF"
+    opts+=" --config-file $NEUTRON_CORE_PLUGIN_CONF"
     local cfg_file
     for cfg_file in ${_NEUTRON_SERVER_EXTRA_CONF_FILES_ABS[@]}; do
         opts+=" --config-file $cfg_file"
@@ -405,7 +402,7 @@
 
     # Start the Neutron service
     # TODO(sc68cal) Stop hard coding this
-    run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $ops"
+    run_process neutron-api "$NEUTRON_BIN_DIR/neutron-server $opts"
 
     if is_ssl_enabled_service "neutron"; then
         ssl_ca="--ca-certificate=${SSL_BUNDLE_FILE}"
@@ -426,20 +423,19 @@
 
 # start_neutron() - Start running processes, including screen
 function start_neutron_new {
-    _set_config_files
-
     # Start up the neutron agents if enabled
     # TODO(sc68cal) Make this pluggable so different DevStack plugins for different Neutron plugins
     # can resolve the $NEUTRON_AGENT_BINARY
     if is_service_enabled neutron-agent; then
-        run_process neutron-agent "$NEUTRON_BIN_DIR/$NEUTRON_AGENT_BINARY $NEUTRON_CONFIG_ARG"
+        # TODO(ihrachys) stop loading ml2_conf.ini into agents, instead load agent specific files
+        run_process neutron-agent "$NEUTRON_BIN_DIR/$NEUTRON_AGENT_BINARY --config-file $NEUTRON_CONF --config-file $NEUTRON_CORE_PLUGIN_CONF"
     fi
     if is_service_enabled neutron-dhcp; then
         neutron_plugin_configure_dhcp_agent $NEUTRON_DHCP_CONF
-        run_process neutron-dhcp "$NEUTRON_BIN_DIR/$NEUTRON_DHCP_BINARY $NEUTRON_CONFIG_ARG"
+        run_process neutron-dhcp "$NEUTRON_BIN_DIR/$NEUTRON_DHCP_BINARY --config-file $NEUTRON_CONF --config-file $NEUTRON_DHCP_CONF"
     fi
     if is_service_enabled neutron-l3; then
-        run_process neutron-l3 "$NEUTRON_BIN_DIR/$NEUTRON_L3_BINARY $NEUTRON_CONFIG_ARG"
+        run_process neutron-l3 "$NEUTRON_BIN_DIR/$NEUTRON_L3_BINARY --config-file $NEUTRON_CONF --config-file $NEUTRON_L3_CONF"
     fi
     if is_service_enabled neutron-api; then
         # XXX(sc68cal) - Here's where plugins can wire up their own networks instead
@@ -454,11 +450,11 @@
         fi
     fi
     if is_service_enabled neutron-metadata-agent; then
-        run_process neutron-metadata-agent "$NEUTRON_BIN_DIR/$NEUTRON_META_BINARY $NEUTRON_CONFIG_ARG"
+        run_process neutron-metadata-agent "$NEUTRON_BIN_DIR/$NEUTRON_META_BINARY --config-file $NEUTRON_CONF --config-file $NEUTRON_META_CONF"
     fi
 
     if is_service_enabled neutron-metering; then
-        run_process neutron-metering "$AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME"
+        run_process neutron-metering "$NEUTRON_METERING_BINARY --config-file $NEUTRON_CONF --config-file $NEUTRON_METERING_AGENT_CONF"
     fi
 }
 
@@ -480,37 +476,16 @@
     fi
 }
 
-# Compile the lost of enabled config files
-function _set_config_files {
-
-    NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_CONF"
-
-    #TODO(sc68cal) OVS and LB agent uses settings in NEUTRON_CORE_PLUGIN_CONF (ml2_conf.ini) but others may not
-    if is_service_enabled neutron-agent; then
-        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_CORE_PLUGIN_CONF"
-    fi
-
-    if is_service_enabled neutron-dhcp; then
-        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_DHCP_CONF"
-    fi
-
-    if is_service_enabled neutron-l3; then
-        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_L3_CONF"
-    fi
-
-    if is_service_enabled neutron-metadata-agent; then
-        NEUTRON_CONFIG_ARG+=" --config-file $NEUTRON_META_CONF"
-    fi
-
-}
-
 # neutron_service_plugin_class_add() - add service plugin class
 function neutron_service_plugin_class_add_new {
     local service_plugin_class=$1
     local plugins=""
 
     plugins=$(iniget $NEUTRON_CONF DEFAULT service_plugins)
-    plugins+=",${service_plugin_class}"
+    if [ $plugins ]; then
+        plugins+=","
+    fi
+    plugins+="${service_plugin_class}"
     iniset $NEUTRON_CONF DEFAULT service_plugins $plugins
 }
 
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index b381b64..ccab527 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -141,10 +141,10 @@
 # These config files are relative to ``/etc/neutron``.  The above
 # example would specify ``--config-file /etc/neutron/file1`` for
 # neutron server.
-declare -a Q_PLUGIN_EXTRA_CONF_FILES
+declare -a -g Q_PLUGIN_EXTRA_CONF_FILES
 
 # same as Q_PLUGIN_EXTRA_CONF_FILES, but with absolute path.
-declare -a _Q_PLUGIN_EXTRA_CONF_FILES_ABS
+declare -a -g _Q_PLUGIN_EXTRA_CONF_FILES_ABS
 
 
 Q_RR_CONF_FILE=$NEUTRON_CONF_DIR/rootwrap.conf
@@ -798,7 +798,7 @@
 }
 
 function _configure_neutron_ceilometer_notifications {
-    iniset $NEUTRON_CONF oslo_messaging_notifications driver messaging
+    iniset $NEUTRON_CONF oslo_messaging_notifications driver messagingv2
 }
 
 function _configure_neutron_metering {
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index dfed49b..f2302e3 100644
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -67,7 +67,9 @@
     fi
     if [[ "$Q_USE_SECGROUP" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
-        enable_kernel_bridge_firewall
+        if ! running_in_container; then
+            enable_kernel_bridge_firewall
+        fi
     else
         iniset /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver neutron.agent.firewall.NoopFirewallDriver
     fi
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index 1a97001..50b9ae5 100644
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -80,7 +80,9 @@
 function _neutron_ovs_base_configure_firewall_driver {
     if [[ "$Q_USE_SECGROUP" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver iptables_hybrid
-        enable_kernel_bridge_firewall
+        if ! running_in_container; then
+            enable_kernel_bridge_firewall
+        fi
     else
         iniset /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver noop
     fi
diff --git a/lib/nova b/lib/nova
index f5ab201..a36a740 100644
--- a/lib/nova
+++ b/lib/nova
@@ -247,7 +247,7 @@
     sudo rm -f $(apache_site_config_for nova-metadata)
 }
 
-# _config_nova_apache_wsgi() - Set WSGI config files of Keystone
+# _config_nova_apache_wsgi() - Set WSGI config files of Nova API
 function _config_nova_apache_wsgi {
     sudo mkdir -p $NOVA_WSGI_DIR
 
@@ -575,7 +575,7 @@
 
     # Set the oslo messaging driver to the typical default. This does not
     # enable notifications, but it will allow them to function when enabled.
-    iniset $NOVA_CONF oslo_messaging_notifications driver "messaging"
+    iniset $NOVA_CONF oslo_messaging_notifications driver "messagingv2"
     iniset_rpc_backend nova $NOVA_CONF
     iniset $NOVA_CONF glance api_servers "${GLANCE_SERVICE_PROTOCOL}://${GLANCE_HOSTPORT}"
 
@@ -631,7 +631,7 @@
 function init_nova_service_user_conf {
     iniset $NOVA_CONF service_user send_service_user_token True
     iniset $NOVA_CONF service_user auth_type password
-    iniset $NOVA_CONF service_user auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT"
+    iniset $NOVA_CONF service_user auth_url "$KEYSTONE_SERVICE_URI"
     iniset $NOVA_CONF service_user username nova
     iniset $NOVA_CONF service_user password "$SERVICE_PASSWORD"
     iniset $NOVA_CONF service_user user_domain_name "$SERVICE_DOMAIN_NAME"
@@ -664,6 +664,10 @@
         $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CELLS_CONF db sync
         $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CELLS_CONF cell create --name=region --cell_type=parent --username=$RABBIT_USERID --hostname=$RABBIT_HOST --port=5672 --password=$RABBIT_PASSWORD --virtual_host=/ --woffset=0 --wscale=1
         $NOVA_BIN_DIR/nova-manage cell create --name=child --cell_type=child --username=$RABBIT_USERID --hostname=$RABBIT_HOST --port=5672 --password=$RABBIT_PASSWORD --virtual_host=child_cell --woffset=0 --wscale=1
+
+        # Creates the single cells v2 cell for the child cell (v1) nova db.
+        nova-manage --config-file $NOVA_CELLS_CONF cell_v2 create_cell \
+            --transport-url $(get_transport_url child_cell) --name 'cell1'
     fi
 }
 
@@ -704,9 +708,13 @@
         recreate_database nova
         recreate_database nova_cell0
 
-        # Migrate nova database. If "nova-manage cell_v2 simple_cell_setup" has
-        # been run this migrates the "nova" and "nova_cell0" database.
-        # Otherwise it just migrates the "nova" database.
+        # map_cell0 will create the cell mapping record in the nova_api DB so
+        # this needs to come after the api_db sync happens. We also want to run
+        # this before the db sync below since that will migrate both the nova
+        # and nova_cell0 databases.
+        nova-manage cell_v2 map_cell0 --database_connection `database_connection_url nova_cell0`
+
+        # Migrate nova and nova_cell0 databases.
         $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF db sync
 
         if is_service_enabled n-cell; then
@@ -716,6 +724,10 @@
         # Run online migrations on the new databases
         # Needed for flavor conversion
         $NOVA_BIN_DIR/nova-manage --config-file $NOVA_CONF db online_data_migrations
+
+        # create the cell1 cell for the main nova db where the hosts live
+        nova-manage cell_v2 create_cell --transport-url $(get_transport_url) \
+            --name 'cell1'
     fi
 
     create_nova_cache_dir
@@ -885,7 +897,9 @@
     run_process n-crt "$NOVA_BIN_DIR/nova-cert --config-file $api_cell_conf"
 
     if is_service_enabled n-net; then
-        enable_kernel_bridge_firewall
+        if ! running_in_container; then
+            enable_kernel_bridge_firewall
+        fi
     fi
     run_process n-net "$NOVA_BIN_DIR/nova-network --config-file $compute_cell_conf"
 
@@ -964,20 +978,6 @@
     fi
 }
 
-# create_cell(): Group the available hosts into a cell
-function create_cell {
-    # NOTE(danms): map_cell0 always returns 1 right now; remove this when that is fixed
-    (nova-manage cell_v2 map_cell0 --database_connection `database_connection_url nova_cell0`|| true)
-
-    if ! is_service_enabled n-cell; then
-        nova-manage cell_v2 simple_cell_setup --transport-url $(get_transport_url)
-    else
-        nova-manage --config-file $NOVA_CELLS_CONF  --verbose cell_v2 map_cell_and_hosts \
-                --transport-url $(get_transport_url child_cell) --name 'cell1'
-        nova-manage db sync
-    fi
-}
-
 # Restore xtrace
 $_XTRACE_LIB_NOVA
 
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 47b054b..56bb6bd 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -34,18 +34,21 @@
         #pip_install_gr <there-si-no-guestfs-in-pypi>
     elif is_fedora || is_suse; then
         # On "KVM for IBM z Systems", kvm does not have its own package
-        if [[ ! ${DISTRO} =~ "kvmibm1" ]]; then
+        if [[ ! ${DISTRO} =~ "kvmibm1" && ! ${DISTRO} =~ "rhel7" ]]; then
             install_package kvm
         fi
-        # there is a dependency issue with kvm (which is really just a
-        # wrapper to qemu-system-x86) that leaves some bios files out,
-        # so install qemu-kvm (which shouldn't strictly be needed, as
-        # everything has been merged into qemu-system-x86) to bring in
-        # the right packages. see
-        # https://bugzilla.redhat.com/show_bug.cgi?id=1235890
-        install_package qemu-kvm
+
+        if [[ ${DISTRO} =~ "rhel7" ]]; then
+            # This should install the latest qemu-kvm build,
+            # which is called qemu-kvm-ev in centos7
+            # (as the default OS qemu-kvm package is usually rather old,
+            # and should be updated by above)
+            install_package qemu-kvm
+        fi
+
         install_package libvirt libvirt-devel
         pip_install_gr libvirt-python
+
     fi
 }
 
diff --git a/lib/placement b/lib/placement
index e7ffe33..4cc5cd8 100644
--- a/lib/placement
+++ b/lib/placement
@@ -100,7 +100,7 @@
 
 function configure_placement_nova_compute {
     iniset $NOVA_CONF placement auth_type "password"
-    iniset $NOVA_CONF placement auth_url "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_AUTH_PORT/v3"
+    iniset $NOVA_CONF placement auth_url "$KEYSTONE_SERVICE_URI/v3"
     iniset $NOVA_CONF placement username placement
     iniset $NOVA_CONF placement password "$SERVICE_PASSWORD"
     iniset $NOVA_CONF placement user_domain_name "$SERVICE_DOMAIN_NAME"
diff --git a/lib/tempest b/lib/tempest
index 128e972..a9461d4 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -17,7 +17,7 @@
 #   - ``PUBLIC_NETWORK_NAME``
 #   - ``VIRT_DRIVER``
 #   - ``LIBVIRT_TYPE``
-#   - ``KEYSTONE_SERVICE_PROTOCOL``, ``KEYSTONE_SERVICE_HOST`` from lib/keystone
+#   - ``KEYSTONE_SERVICE_URI``, ``KEYSTONE_SERVICE_URI_V3`` from lib/keystone
 #
 # Optional Dependencies:
 #
@@ -257,7 +257,7 @@
     iniset $TEMPEST_CONFIG volume build_timeout $BUILD_TIMEOUT
 
     # Identity
-    iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
+    iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_URI/v2.0/"
     iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_URI_V3"
     iniset $TEMPEST_CONFIG identity user_lockout_failure_attempts $KEYSTONE_LOCKOUT_FAILURE_ATTEMPTS
     iniset $TEMPEST_CONFIG identity user_lockout_duration $KEYSTONE_LOCKOUT_DURATION
@@ -273,13 +273,11 @@
     if [ "$ENABLE_IDENTITY_V2" == "True" ]; then
         # Run Identity API v2 tests ONLY if needed
         iniset $TEMPEST_CONFIG identity-feature-enabled api_v2 True
-        iniset $TEMPEST_CONFIG identity auth_version ${TEMPEST_AUTH_VERSION:-v2}
     else
         # Skip Identity API v2 tests by default
         iniset $TEMPEST_CONFIG identity-feature-enabled api_v2 False
-        # Use v3 auth tokens for running all Tempest tests
-        iniset $TEMPEST_CONFIG identity auth_version v3
     fi
+    iniset $TEMPEST_CONFIG identity auth_version ${TEMPEST_AUTH_VERSION:-v3}
 
     if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
         iniset $TEMPEST_CONFIG identity ca_certificates_file $SSL_BUNDLE_FILE
@@ -290,6 +288,10 @@
         iniset $TEMPEST_CONFIG identity-feature-enabled security_compliance True
     fi
 
+    # TODO(rodrigods): This is a feature flag for bug 1590578 which is fixed in
+    # Newton and Ocata. This option can be removed after Mitaka is end of life.
+    iniset $TEMPEST_CONFIG identity-feature-enabled forbid_global_implied_dsr True
+
     # Image
     # We want to be able to override this variable in the gate to avoid
     # doing an external HTTP fetch for this test.
diff --git a/stack.sh b/stack.sh
index 94315e1..f08d56f 100755
--- a/stack.sh
+++ b/stack.sh
@@ -761,6 +761,7 @@
 run_phase stack pre-install
 
 install_rpc_backend
+restart_rpc_backend
 
 # NOTE(sdague): dlm install is conditional on one being enabled by configuration
 install_dlm
@@ -952,11 +953,6 @@
 fi
 
 
-# Finalize queue installation
-# ----------------------------
-restart_rpc_backend
-
-
 # Export Certificate Authority Bundle
 # -----------------------------------
 
@@ -1061,11 +1057,18 @@
     fi
 
     create_keystone_accounts
-    create_nova_accounts
-    create_glance_accounts
-    create_cinder_accounts
-    create_neutron_accounts
-
+    if is_service_enabled nova; then
+        create_nova_accounts
+    fi
+    if is_service_enabled glance; then
+        create_glance_accounts
+    fi
+    if is_service_enabled cinder; then
+        create_cinder_accounts
+    fi
+    if is_service_enabled neutron; then
+        create_neutron_accounts
+    fi
     if is_service_enabled swift; then
         create_swift_accounts
     fi
@@ -1368,7 +1371,7 @@
 # Do this late because it requires compute hosts to have started
 if is_service_enabled n-api; then
     if is_service_enabled n-cpu; then
-        create_cell
+        $TOP_DIR/tools/discover_hosts.sh
     else
         # Some CI systems like Hyper-V build the control plane on
         # Linux, and join in non Linux Computes after setup. This
diff --git a/stackrc b/stackrc
index afe385c..c3b94d0 100644
--- a/stackrc
+++ b/stackrc
@@ -5,7 +5,7 @@
 
 # ensure we don't re-source this in the same environment
 [[ -z "$_DEVSTACK_STACKRC" ]] || return 0
-declare -r _DEVSTACK_STACKRC=1
+declare -r -g _DEVSTACK_STACKRC=1
 
 # Find the other rc files
 RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
@@ -102,9 +102,19 @@
     source $RC_DIR/.localrc.password
 fi
 
-# Control whether Python 3 should be used.
+# Control whether Python 3 should be used at all.
 export USE_PYTHON3=$(trueorfalse False USE_PYTHON3)
 
+# Control whether Python 3 is enabled for specific services by the
+# base name of the directory from which they are installed. See
+# enable_python3_package to edit this variable and use_python3_for to
+# test membership.
+export ENABLED_PYTHON3_PACKAGES="nova,glance,cinder,uwsgi,python-openstackclient"
+
+# Explicitly list services not to run under Python 3. See
+# disable_python3_package to edit this variable.
+export DISABLED_PYTHON3_PACKAGES=""
+
 # When Python 3 is supported by an application, adding the specific
 # version of Python 3 to this variable will install the app using that
 # version of the interpreter instead of 2.7.
@@ -626,9 +636,6 @@
         IMAGE_URLS+=","
     fi
     case "$VIRT_DRIVER" in
-        openvz)
-            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ubuntu-12.04-x86_64}
-            IMAGE_URLS+="http://download.openvz.org/template/precreated/ubuntu-12.04-x86_64.tar.gz";;
         libvirt)
             case "$LIBVIRT_TYPE" in
                 lxc) # the cirros root disk in the uec tarball is empty, so it will not work for lxc
@@ -646,13 +653,6 @@
             DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.4-x86_64-disk}
             IMAGE_URLS+="http://ca.downloads.xensource.com/OpenStack/cirros-0.3.4-x86_64-disk.vhd.tgz"
             IMAGE_URLS+=",http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz";;
-        ironic)
-            # NOTE(lucasagomes): The logic setting the default image
-            # now lives in the Ironic tree
-            ;;
-        *) # Default to Cirros qcow2 image file
-            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img}
-            IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img";;
     esac
     DOWNLOAD_DEFAULT_IMAGES=False
 fi
diff --git a/tests/test_python.sh b/tests/test_python.sh
new file mode 100755
index 0000000..8652798
--- /dev/null
+++ b/tests/test_python.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+# Tests for DevStack INI functions
+
+TOP=$(cd $(dirname "$0")/.. && pwd)
+
+source $TOP/functions-common
+source $TOP/inc/python
+
+source $TOP/tests/unittest.sh
+
+echo "Testing Python 3 functions"
+
+# Initialize variables manipulated by functions under test.
+export ENABLED_PYTHON3_PACKAGES=""
+export DISABLED_PYTHON3_PACKAGES=""
+
+assert_false "should not be enabled yet" python3_enabled_for testpackage1
+
+enable_python3_package testpackage1
+assert_equal "$ENABLED_PYTHON3_PACKAGES" "testpackage1"  "unexpected result"
+assert_true "should be enabled" python3_enabled_for testpackage1
+
+assert_false "should not be disabled yet" python3_disabled_for testpackage2
+
+disable_python3_package testpackage2
+assert_equal "$DISABLED_PYTHON3_PACKAGES" "testpackage2"  "unexpected result"
+assert_true "should be disabled" python3_disabled_for testpackage2
+
+report_results
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index a5ccb19..dbe5278 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -144,6 +144,9 @@
 fi
 
 set -x
-pip_install -U setuptools
+
+# Note setuptools is part of requirements.txt and we want to make sure
+# we obey any versioning as described there.
+pip_install_gr setuptools
 
 get_versions