Merge "nova: call map_cell0 much earlier in the setup"
diff --git a/doc/source/index.rst b/doc/source/index.rst
index b8dd506..edd6595 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -56,15 +56,15 @@
 
 ::
 
-   $ adduser stack
+   $ sudo adduser stack
 
 Since this user will be making many changes to your system, it should
 have sudo privileges:
 
 ::
 
-    $ echo "stack ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
-    $ su stack
+    $ sudo tee <<<"stack ALL=(ALL) NOPASSWD: ALL" /etc/sudoers
+    $ sudo su - stack
 
 Download DevStack
 -----------------
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 4cfbcb1..17da67b 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -80,6 +80,7 @@
 manila-ui                              `git://git.openstack.org/openstack/manila-ui <https://git.openstack.org/cgit/openstack/manila-ui>`__
 masakari                               `git://git.openstack.org/openstack/masakari <https://git.openstack.org/cgit/openstack/masakari>`__
 meteos                                 `git://git.openstack.org/openstack/meteos <https://git.openstack.org/cgit/openstack/meteos>`__
+meteos-ui                              `git://git.openstack.org/openstack/meteos-ui <https://git.openstack.org/cgit/openstack/meteos-ui>`__
 mistral                                `git://git.openstack.org/openstack/mistral <https://git.openstack.org/cgit/openstack/mistral>`__
 mixmatch                               `git://git.openstack.org/openstack/mixmatch <https://git.openstack.org/cgit/openstack/mixmatch>`__
 mogan                                  `git://git.openstack.org/openstack/mogan <https://git.openstack.org/cgit/openstack/mogan>`__
@@ -122,7 +123,6 @@
 neutron-lbaas                          `git://git.openstack.org/openstack/neutron-lbaas <https://git.openstack.org/cgit/openstack/neutron-lbaas>`__
 neutron-lbaas-dashboard                `git://git.openstack.org/openstack/neutron-lbaas-dashboard <https://git.openstack.org/cgit/openstack/neutron-lbaas-dashboard>`__
 neutron-vpnaas                         `git://git.openstack.org/openstack/neutron-vpnaas <https://git.openstack.org/cgit/openstack/neutron-vpnaas>`__
-nova-docker                            `git://git.openstack.org/openstack/nova-docker <https://git.openstack.org/cgit/openstack/nova-docker>`__
 nova-dpm                               `git://git.openstack.org/openstack/nova-dpm <https://git.openstack.org/cgit/openstack/nova-dpm>`__
 nova-lxd                               `git://git.openstack.org/openstack/nova-lxd <https://git.openstack.org/cgit/openstack/nova-lxd>`__
 nova-mksproxy                          `git://git.openstack.org/openstack/nova-mksproxy <https://git.openstack.org/cgit/openstack/nova-mksproxy>`__
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-common b/functions-common
index 8d32bb4..0d1b01f 100644
--- a/functions-common
+++ b/functions-common
@@ -302,9 +302,9 @@
 # such as "install_package" further abstract things in better ways.
 #
 # ``os_VENDOR`` - vendor name: ``Ubuntu``, ``Fedora``, etc
-# ``os_RELEASE`` - major release: ``14.04`` (Ubuntu), ``20`` (Fedora)
+# ``os_RELEASE`` - major release: ``16.04`` (Ubuntu), ``23`` (Fedora)
 # ``os_PACKAGE`` - package type: ``deb`` or ``rpm``
-# ``os_CODENAME`` - vendor's codename for release: ``trusty``
+# ``os_CODENAME`` - vendor's codename for release: ``xenial``
 
 declare os_VENDOR os_RELEASE os_PACKAGE os_CODENAME
 
@@ -992,7 +992,7 @@
 }
 
 # Gets or creates endpoint
-# Usage: get_or_create_endpoint <service> <region> <publicurl> <adminurl> <internalurl>
+# Usage: get_or_create_endpoint <service> <region> <publicurl> [adminurl] [internalurl]
 function get_or_create_endpoint {
     # NOTE(jamielennnox): when converting to v3 endpoint creation we go from
     # creating one endpoint with multiple urls to multiple endpoints each with
@@ -1004,9 +1004,13 @@
     # endpoints they need.
     local public_id
     public_id=$(_get_or_create_endpoint_with_interface $1 public $3 $2)
-    _get_or_create_endpoint_with_interface $1 admin $4 $2
-    _get_or_create_endpoint_with_interface $1 internal $5 $2
-
+    # only create admin/internal urls if provided content for them
+    if [[ -n "$4" ]]; then
+        _get_or_create_endpoint_with_interface $1 admin $4 $2
+    fi
+    if [[ -n "$5" ]]; then
+        _get_or_create_endpoint_with_interface $1 internal $5 $2
+    fi
     # return the public id to indicate success, and this is the endpoint most likely wanted
     echo $public_id
 }
diff --git a/inc/python b/inc/python
index 5afc07f..2bdc097 100644
--- a/inc/python
+++ b/inc/python
@@ -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 870ee0b..767fd00 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -125,12 +125,6 @@
     done
 fi
 
-# Change the default nova_catalog_info and nova_catalog_admin_info values in
-# cinder so that the service name cinder is searching for matches that set for
-# nova in keystone.
-CINDER_NOVA_CATALOG_INFO=${CINDER_NOVA_CATALOG_INFO:-compute:nova:publicURL}
-CINDER_NOVA_CATALOG_ADMIN_INFO=${CINDER_NOVA_CATALOG_ADMIN_INFO:-compute:nova:adminURL}
-
 # Environment variables to configure the image-volume cache
 CINDER_IMG_CACHE_ENABLED=${CINDER_IMG_CACHE_ENABLED:-True}
 
@@ -268,8 +262,15 @@
 
     configure_auth_token_middleware $CINDER_CONF cinder $CINDER_AUTH_CACHE_DIR
 
-    iniset $CINDER_CONF DEFAULT nova_catalog_info $CINDER_NOVA_CATALOG_INFO
-    iniset $CINDER_CONF DEFAULT nova_catalog_admin_info $CINDER_NOVA_CATALOG_ADMIN_INFO
+    # Change the default nova_catalog_info and nova_catalog_admin_info values in
+    # cinder so that the service name cinder is searching for matches that set for
+    # nova in keystone.
+    if [[ -n "$CINDER_NOVA_CATALOG_INFO" ]]; then
+        iniset $CINDER_CONF DEFAULT nova_catalog_info $CINDER_NOVA_CATALOG_INFO
+    fi
+    if [[ -n "$CINDER_NOVA_CATALOG_ADMIN_INFO" ]]; then
+        iniset $CINDER_CONF DEFAULT nova_catalog_admin_info $CINDER_NOVA_CATALOG_ADMIN_INFO
+    fi
 
     iniset $CINDER_CONF DEFAULT auth_strategy keystone
     iniset $CINDER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -395,24 +396,18 @@
         get_or_create_endpoint \
             "volume" \
             "$REGION_NAME" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(project_id)s" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(project_id)s" \
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v1/\$(project_id)s"
 
         get_or_create_service "cinderv2" "volumev2" "Cinder Volume Service V2"
         get_or_create_endpoint \
             "volumev2" \
             "$REGION_NAME" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s" \
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v2/\$(project_id)s"
 
         get_or_create_service "cinderv3" "volumev3" "Cinder Volume Service V3"
         get_or_create_endpoint \
             "volumev3" \
             "$REGION_NAME" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s" \
-            "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s" \
             "$CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT/v3/\$(project_id)s"
 
         configure_cinder_internal_tenant
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/databases/mysql b/lib/databases/mysql
index 89ae082..7bbcace 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -94,7 +94,7 @@
     # Change bind-address from localhost (127.0.0.1) to any (::) and
     # set default db type to InnoDB
     iniset -sudo $my_conf mysqld bind-address "$SERVICE_LISTEN_ADDRESS"
-    iniset -sudo $my_conf mysqld sql_mode STRICT_ALL_TABLES
+    iniset -sudo $my_conf mysqld sql_mode TRADITIONAL
     iniset -sudo $my_conf mysqld default-storage-engine InnoDB
     iniset -sudo $my_conf mysqld max_connections 1024
     iniset -sudo $my_conf mysqld query_cache_type OFF
diff --git a/lib/databases/postgresql b/lib/databases/postgresql
index 1f347f5..618834b 100644
--- a/lib/databases/postgresql
+++ b/lib/databases/postgresql
@@ -95,6 +95,7 @@
 
 function install_database_postgresql {
     echo_summary "Installing postgresql"
+    deprecated "Use of postgresql in devstack is deprecated, and will be removed during the Pike cycle"
     local pgpass=$HOME/.pgpass
     if [[ ! -e $pgpass ]]; then
         cat <<EOF > $pgpass
diff --git a/lib/glance b/lib/glance
index 26c4150..58f1def 100644
--- a/lib/glance
+++ b/lib/glance
@@ -314,8 +314,6 @@
         get_or_create_endpoint \
             "image" \
             "$REGION_NAME" \
-            "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \
-            "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT" \
             "$GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT"
 
         # Note(frickler): Crude workaround for https://bugs.launchpad.net/glance-store/+bug/1620999
@@ -331,8 +329,6 @@
 
         get_or_create_endpoint "artifact" \
             "$REGION_NAME" \
-            "$GLANCE_SERVICE_PROTOCOL://$GLANCE_GLARE_HOSTPORT" \
-            "$GLANCE_SERVICE_PROTOCOL://$GLANCE_GLARE_HOSTPORT" \
             "$GLANCE_SERVICE_PROTOCOL://$GLANCE_GLARE_HOSTPORT"
     fi
 }
diff --git a/lib/keystone b/lib/keystone
index 474af8b..530f3b4 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -384,8 +384,7 @@
     admin_project=$(openstack project show "admin" -f value -c id)
     local admin_user
     admin_user=$(openstack user show "admin" -f value -c id)
-    local admin_role
-    admin_role=$(openstack role show "admin" -f value -c id)
+    local admin_role="admin"
 
     get_or_add_user_domain_role $admin_role $admin_user default
 
@@ -403,13 +402,20 @@
     get_or_create_role ResellerAdmin
 
     # The Member role is used by Horizon and Swift so we need to keep it:
-    local member_role
-    member_role=$(get_or_create_role "Member")
+    local member_role="member"
+
+    # Captial Member role is legacy hard coded in Horizon / Swift
+    # configs. Keep it around.
+    get_or_create_role "Member"
+
+    # The reality is that the rest of the roles listed below honestly
+    # should work by symbolic names.
+    get_or_create_role $member_role
 
     # another_role demonstrates that an arbitrary role may be created and used
     # TODO(sleepsonthefloor): show how this can be used for rbac in the future!
-    local another_role
-    another_role=$(get_or_create_role "anotherrole")
+    local another_role="anotherrole"
+    get_or_create_role $another_role
 
     # invisible project - admin can't see this one
     local invis_project
@@ -654,8 +660,7 @@
         --bootstrap-service-name keystone \
         --bootstrap-region-id "$REGION_NAME" \
         --bootstrap-admin-url "$KEYSTONE_AUTH_URI" \
-        --bootstrap-public-url "$KEYSTONE_SERVICE_URI" \
-        --bootstrap-internal-url "$KEYSTONE_SERVICE_URI"
+        --bootstrap-public-url "$KEYSTONE_SERVICE_URI"
 }
 
 # Restore xtrace
diff --git a/lib/neutron b/lib/neutron
index f6c705c..f277062 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -219,6 +219,7 @@
 
         iniset $NEUTRON_META_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
         iniset $NEUTRON_META_CONF DEFAULT nova_metadata_ip $SERVICE_HOST
+        iniset $NEUTRON_META_CONF DEFAULT metadata_workers $API_WORKERS
         iniset $NEUTRON_META_CONF agent root_helper_daemon "$NEUTRON_ROOTWRAP_DAEMON_CMD"
 
         # TODO(dtroyer): remove the v2.0 hard code below
@@ -329,8 +330,6 @@
             "network" "Neutron Service")
         get_or_create_endpoint $neutron_service \
             "$REGION_NAME" \
-            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/" \
-            "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/" \
             "$NEUTRON_SERVICE_PROTOCOL://$NEUTRON_SERVICE_HOST:$NEUTRON_SERVICE_PORT/"
     fi
 }
@@ -396,9 +395,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"
@@ -406,7 +405,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}"
@@ -511,7 +510,10 @@
     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 5ec61f9..b381b64 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -359,6 +359,10 @@
     fi
 
     iniset $NEUTRON_CONF DEFAULT api_workers "$API_WORKERS"
+    # devstack is not a tool for running uber scale OpenStack
+    # clouds, therefore running without a dedicated RPC worker
+    # for state reports is more than adequate.
+    iniset $NEUTRON_CONF DEFAULT rpc_state_report_workers 0
 }
 
 function create_nova_conf_neutron {
@@ -406,8 +410,6 @@
         get_or_create_endpoint \
             "network" \
             "$REGION_NAME" \
-            "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/" \
-            "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/" \
             "$Q_PROTOCOL://$SERVICE_HOST:$Q_PORT/"
     fi
 }
@@ -788,6 +790,7 @@
 
     iniset $Q_META_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $Q_META_CONF_FILE DEFAULT nova_metadata_ip $Q_META_DATA_IP
+    iniset $Q_META_CONF_FILE DEFAULT metadata_workers $API_WORKERS
     iniset $Q_META_CONF_FILE AGENT root_helper "$Q_RR_COMMAND"
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
         iniset $Q_META_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
diff --git a/lib/neutron_plugins/README.md b/lib/neutron_plugins/README.md
index f03000e..ed40886 100644
--- a/lib/neutron_plugins/README.md
+++ b/lib/neutron_plugins/README.md
@@ -24,7 +24,6 @@
 * ``neutron_plugin_configure_common`` :
   set plugin-specific variables, ``Q_PLUGIN_CONF_PATH``, ``Q_PLUGIN_CONF_FILENAME``,
   ``Q_PLUGIN_CLASS``
-* ``neutron_plugin_configure_debug_command``
 * ``neutron_plugin_configure_dhcp_agent``
 * ``neutron_plugin_configure_l3_agent``
 * ``neutron_plugin_configure_plugin_agent``
diff --git a/lib/neutron_plugins/bigswitch_floodlight b/lib/neutron_plugins/bigswitch_floodlight
index 586ded7..52c6ad5 100644
--- a/lib/neutron_plugins/bigswitch_floodlight
+++ b/lib/neutron_plugins/bigswitch_floodlight
@@ -26,10 +26,6 @@
     BS_FL_CONTROLLER_TIMEOUT=${BS_FL_CONTROLLER_TIMEOUT:-10}
 }
 
-function neutron_plugin_configure_debug_command {
-    _neutron_ovs_base_configure_debug_command
-}
-
 function neutron_plugin_configure_dhcp_agent {
     :
 }
diff --git a/lib/neutron_plugins/brocade b/lib/neutron_plugins/brocade
index 6ba0a66..310b72e 100644
--- a/lib/neutron_plugins/brocade
+++ b/lib/neutron_plugins/brocade
@@ -49,16 +49,11 @@
 
 }
 
-function neutron_plugin_configure_debug_command {
-    iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge
-}
-
 function neutron_plugin_configure_dhcp_agent {
     iniset $Q_DHCP_CONF_FILE DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
 }
 
 function neutron_plugin_configure_l3_agent {
-    iniset $Q_L3_CONF_FILE DEFAULT external_network_bridge
     iniset $Q_L3_CONF_FILE DEFAULT l3_agent_manager neutron.agent.l3_agent.L3NATAgentWithStateReport
 }
 
diff --git a/lib/neutron_plugins/cisco b/lib/neutron_plugins/cisco
index fc2cb8a..b397169 100644
--- a/lib/neutron_plugins/cisco
+++ b/lib/neutron_plugins/cisco
@@ -45,7 +45,6 @@
 _prefix_function neutron_plugin_create_nova_conf ovs
 _prefix_function neutron_plugin_install_agent_packages ovs
 _prefix_function neutron_plugin_configure_common ovs
-_prefix_function neutron_plugin_configure_debug_command ovs
 _prefix_function neutron_plugin_configure_dhcp_agent ovs
 _prefix_function neutron_plugin_configure_l3_agent ovs
 _prefix_function neutron_plugin_configure_plugin_agent ovs
@@ -83,10 +82,6 @@
     Q_PLUGIN_CLASS="neutron.plugins.cisco.network_plugin.PluginV2"
 }
 
-function neutron_plugin_configure_debug_command {
-    :
-}
-
 function neutron_plugin_configure_dhcp_agent {
     iniset $Q_DHCP_CONF_FILE DEFAULT dhcp_agent_manager neutron.agent.dhcp_agent.DhcpAgentWithStateReport
 }
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index 0c8ccb8..dfed49b 100644
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -8,6 +8,7 @@
 set +o xtrace
 
 function neutron_lb_cleanup {
+    sudo ip link set $PUBLIC_BRIDGE down
     sudo brctl delbr $PUBLIC_BRIDGE
 
     if [[ "$Q_ML2_TENANT_NETWORK_TYPE" = "vxlan" ]]; then
@@ -38,10 +39,6 @@
     install_package bridge-utils
 }
 
-function neutron_plugin_configure_debug_command {
-    iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge
-}
-
 function neutron_plugin_configure_dhcp_agent {
     local conf_file=$1
     :
@@ -51,7 +48,6 @@
     local conf_file=$1
     sudo brctl addbr $PUBLIC_BRIDGE
     set_mtu $PUBLIC_BRIDGE $PUBLIC_BRIDGE_MTU
-    iniset $conf_file DEFAULT external_network_bridge
 }
 
 function neutron_plugin_configure_plugin_agent {
diff --git a/lib/neutron_plugins/nuage b/lib/neutron_plugins/nuage
index 61e634e..1c04aaa 100644
--- a/lib/neutron_plugins/nuage
+++ b/lib/neutron_plugins/nuage
@@ -33,10 +33,6 @@
     NUAGE_CNA_DEF_NETPART_NAME=${NUAGE_CNA_DEF_NETPART_NAME:-''}
 }
 
-function neutron_plugin_configure_debug_command {
-    :
-}
-
 function neutron_plugin_configure_dhcp_agent {
     :
 }
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 76a1a4f..acab582 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -23,10 +23,6 @@
     _neutron_ovs_base_install_agent_packages
 }
 
-function neutron_plugin_configure_debug_command {
-    _neutron_ovs_base_configure_debug_command
-}
-
 function neutron_plugin_configure_dhcp_agent {
     local conf_file=$1
     :
@@ -81,8 +77,11 @@
         # integration bridge.  This is enabled by using a root wrapper
         # that executes commands on dom0 via a XenAPI plugin.
         # XenAPI does not support daemon rootwrap now, so set root_helper_daemon empty
-        iniset "/$Q_PLUGIN_CONF_FILE.domU" agent root_helper "$Q_RR_DOM0_COMMAND"
-        iniset "/$Q_PLUGIN_CONF_FILE.domU" agent root_helper_daemon ""
+        iniset "/$Q_PLUGIN_CONF_FILE.domU" agent root_helper ""
+        iniset "/$Q_PLUGIN_CONF_FILE.domU" agent root_helper_daemon "xenapi_root_helper"
+        iniset "/$Q_PLUGIN_CONF_FILE.domU" xenapi connection_url "$XENAPI_CONNECTION_URL"
+        iniset "/$Q_PLUGIN_CONF_FILE.domU" xenapi connection_username "$XENAPI_USER"
+        iniset "/$Q_PLUGIN_CONF_FILE.domU" xenapi connection_password "$XENAPI_PASSWORD"
 
         # Disable minimize polling, so that it can always detect OVS and Port changes
         # This is a problem of xenserver + neutron, bug has been reported
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index 62a4d00..1a97001 100644
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -77,14 +77,6 @@
     fi
 }
 
-function _neutron_ovs_base_configure_debug_command {
-    if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" = "True" ]; then
-        iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge ""
-    else
-        iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT external_network_bridge $PUBLIC_BRIDGE
-    fi
-}
-
 function _neutron_ovs_base_configure_firewall_driver {
     if [[ "$Q_USE_SECGROUP" == "True" ]]; then
         iniset /$Q_PLUGIN_CONF_FILE securitygroup firewall_driver iptables_hybrid
@@ -95,9 +87,7 @@
 }
 
 function _neutron_ovs_base_configure_l3_agent {
-    if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" = "True" ]; then
-        iniset $Q_L3_CONF_FILE DEFAULT external_network_bridge ""
-    else
+    if [ "$Q_USE_PROVIDERNET_FOR_PUBLIC" != "True" ]; then
         iniset $Q_L3_CONF_FILE DEFAULT external_network_bridge $PUBLIC_BRIDGE
     fi
 
diff --git a/lib/neutron_plugins/services/l3 b/lib/neutron_plugins/services/l3
index cd0c1ed..e87a30c 100644
--- a/lib/neutron_plugins/services/l3
+++ b/lib/neutron_plugins/services/l3
@@ -292,8 +292,8 @@
         subnet_params+="--gateway $IPV6_PRIVATE_NETWORK_GATEWAY "
     fi
     subnet_params+="${SUBNETPOOL_V6_ID:+--subnet-pool $SUBNETPOOL_V6_ID} "
-    subnet_params+="${fixed_range_v6:+--subnet-range $fixed_range_v6 $ipv6_modes} "
-    subnet_params+="--network $NET_ID $IPV6_PRIVATE_SUBNET_NAME "
+    subnet_params+="${fixed_range_v6:+--subnet-range $fixed_range_v6} "
+    subnet_params+="$ipv6_modes --network $NET_ID $IPV6_PRIVATE_SUBNET_NAME "
     local ipv6_subnet_id
     ipv6_subnet_id=$(openstack --os-cloud devstack-admin --os-region "$REGION_NAME" subnet create $subnet_params | grep ' id ' | get_field 2)
     die_if_not_set $LINENO ipv6_subnet_id "Failure creating private IPv6 subnet for $project_id"
@@ -385,7 +385,7 @@
     # If the external network has not already been set as the default router
     # gateway when configuring an IPv4 public subnet, do so now
     if [[ "$IP_VERSION" == "6" ]]; then
-        openstack --os-cloud devstack-admin --os-region "$REGION_NAME" set --external-gateway $EXT_NET_ID $ROUTER_ID
+        openstack --os-cloud devstack-admin --os-region "$REGION_NAME" router set --external-gateway $EXT_NET_ID $ROUTER_ID
     fi
 
     # This logic is specific to using the l3-agent for layer 3
diff --git a/lib/nova b/lib/nova
index ba9cac5..0ce6699 100644
--- a/lib/nova
+++ b/lib/nova
@@ -161,6 +161,14 @@
 TEST_FLOATING_POOL=${TEST_FLOATING_POOL:-test}
 TEST_FLOATING_RANGE=${TEST_FLOATING_RANGE:-192.168.253.0/29}
 
+# Other Nova configurations
+# ----------------------------
+
+# ``NOVA_USE_SERVICE_TOKEN`` is a mode where service token is passed along with
+# user token while communicating to external RESP API's like Neutron, Cinder
+# and Glance.
+NOVA_USE_SERVICE_TOKEN=$(trueorfalse False NOVA_USE_SERVICE_TOKEN)
+
 # Functions
 # ---------
 
@@ -239,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
 
@@ -407,16 +415,12 @@
         get_or_create_endpoint \
             "compute_legacy" \
             "$REGION_NAME" \
-            "$nova_api_url/v2/\$(project_id)s" \
-            "$nova_api_url/v2/\$(project_id)s" \
             "$nova_api_url/v2/\$(project_id)s"
 
         get_or_create_service "nova" "compute" "Nova Compute Service"
         get_or_create_endpoint \
             "compute" \
             "$REGION_NAME" \
-            "$nova_api_url/v2.1" \
-            "$nova_api_url/v2.1" \
             "$nova_api_url/v2.1"
     fi
 
@@ -618,12 +622,29 @@
     fi
 
     iniset $NOVA_CONF DEFAULT dhcpbridge_flagfile "$NOVA_CONF_DIR/nova-dhcpbridge.conf"
+
+    if [ "$NOVA_USE_SERVICE_TOKEN" == "True" ]; then
+        init_nova_service_user_conf
+    fi
+}
+
+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 username nova
+    iniset $NOVA_CONF service_user password "$SERVICE_PASSWORD"
+    iniset $NOVA_CONF service_user user_domain_name "$SERVICE_DOMAIN_NAME"
+    iniset $NOVA_CONF service_user project_name "$SERVICE_PROJECT_NAME"
+    iniset $NOVA_CONF service_user project_domain_name "$SERVICE_DOMAIN_NAME"
+    iniset $NOVA_CONF service_user auth_strategy keystone
 }
 
 function init_nova_cells {
     if is_service_enabled n-cell; then
         cp $NOVA_CONF $NOVA_CELLS_CONF
         iniset $NOVA_CELLS_CONF database connection `database_connection_url $NOVA_CELLS_DB`
+        rpc_backend_add_vhost child_cell
         iniset_rpc_backend nova $NOVA_CELLS_CONF DEFAULT child_cell
         iniset $NOVA_CELLS_CONF DEFAULT dhcpbridge_flagfile $NOVA_CELLS_CONF
         iniset $NOVA_CELLS_CONF cells enable True
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 5e7695a..d225ef8 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -26,7 +26,7 @@
         install_package qemu-system
         install_package libvirt-bin libvirt-dev
         pip_install_gr libvirt-python
-        if [[ "$EBTABLES_RACE_FIX" == "True" ]]; then
+        if [[ ${DISTRO} == "trusty" && ${EBTABLES_RACE_FIX} == "True" ]]; then
             # Work around for bug #1501558. We can remove this once we
             # get to a version of Ubuntu that has new enough libvirt.
             TOP_DIR=$TOP_DIR $TOP_DIR/tools/install_ebtables_workaround.sh
@@ -34,18 +34,23 @@
         #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
+            # On centos7 install the qemu-kvm-ev package, which is a
+            # later version of qemu-kvm rebuilt from the qemu-kvm-rhev
+            # package by the virt SIG (as required by nova).  This
+            # package is only provided for RHOS (openstack) or RHV
+            # (ovirt) in RHEL.  We have already insalled the RDO
+            # repositories which provide this.
+            install_package qemu-kvm-ev
+        fi
+
         install_package libvirt libvirt-devel
         pip_install_gr libvirt-python
+
     fi
 }
 
diff --git a/lib/placement b/lib/placement
index 871e282..e7ffe33 100644
--- a/lib/placement
+++ b/lib/placement
@@ -132,8 +132,6 @@
     get_or_create_endpoint \
         "placement" \
         "$REGION_NAME" \
-        "$placement_api_url" \
-        "$placement_api_url" \
         "$placement_api_url"
 }
 
diff --git a/lib/rpc_backend b/lib/rpc_backend
index a21f781..3c1404e 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -97,13 +97,20 @@
 
             break
         done
-        if is_service_enabled n-cell; then
-            # Add partitioned access for the child cell
-            if [ -z `sudo rabbitmqctl list_vhosts | grep child_cell` ]; then
-                sudo rabbitmqctl add_vhost child_cell
-                sudo rabbitmqctl set_permissions -p child_cell $RABBIT_USERID ".*" ".*" ".*"
-            fi
+    fi
+}
+
+# adds a vhost to the rpc backend
+function rpc_backend_add_vhost {
+    local vhost="$1"
+    if is_service_enabled rabbit; then
+        if [ -z `sudo rabbitmqctl list_vhosts | grep $vhost` ]; then
+            sudo rabbitmqctl add_vhost $vhost
+            sudo rabbitmqctl set_permissions -p $vhost $RABBIT_USERID ".*" ".*" ".*"
         fi
+    else
+        echo 'RPC backend does not support vhosts'
+        return 1
     fi
 }
 
diff --git a/lib/swift b/lib/swift
index 03fd454..5b510e5 100644
--- a/lib/swift
+++ b/lib/swift
@@ -636,8 +636,7 @@
         "object-store" \
         "$REGION_NAME" \
         "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT/v1/AUTH_\$(project_id)s" \
-        "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT" \
-        "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT/v1/AUTH_\$(project_id)s"
+        "$SWIFT_SERVICE_PROTOCOL://$SERVICE_HOST:$SWIFT_DEFAULT_BIND_PORT"
 
     local swift_project_test1
     swift_project_test1=$(get_or_create_project swiftprojecttest1 default)
diff --git a/lib/tempest b/lib/tempest
index 7cafadb..128e972 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -48,10 +48,6 @@
 TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf
 TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest}
 
-NOVA_SOURCE_DIR=$DEST/nova
-
-BUILD_INTERVAL=1
-
 # This is the timeout that tempest will wait for a VM to change state,
 # spawn, delete, etc.
 # The default is set to 196 seconds.
@@ -377,8 +373,11 @@
         fi
     fi
 
+    if is_service_enabled n-novnc; then
+        iniset $TEMPEST_CONFIG compute-feature-enabled vnc_console True
+    fi
+
     # Network
-    iniset $TEMPEST_CONFIG network api_version 2.0
     iniset $TEMPEST_CONFIG network project_networks_reachable false
     iniset $TEMPEST_CONFIG network public_network_id "$public_network_id"
     iniset $TEMPEST_CONFIG network public_router_id "$public_router_id"
@@ -412,14 +411,11 @@
         iniset $TEMPEST_CONFIG scenario img_disk_format vhd
         iniset $TEMPEST_CONFIG scenario img_container_format ovf
     else
-        SCENARIO_IMAGE_DIR=${SCENARIO_IMAGE_DIR:-$FILES/images/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
-        SCENARIO_IMAGE_FILE="cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img"
+        SCENARIO_IMAGE_DIR=${SCENARIO_IMAGE_DIR:-$FILES}
+        SCENARIO_IMAGE_FILE=$DEFAULT_IMAGE_NAME
     fi
     iniset $TEMPEST_CONFIG scenario img_dir $SCENARIO_IMAGE_DIR
     iniset $TEMPEST_CONFIG scenario img_file $SCENARIO_IMAGE_FILE
-    iniset $TEMPEST_CONFIG scenario ami_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-blank.img"
-    iniset $TEMPEST_CONFIG scenario ari_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-initrd"
-    iniset $TEMPEST_CONFIG scenario aki_img_file "cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-vmlinuz"
 
     # If using provider networking, use the physical network for validation rather than private
     TEMPEST_SSH_NETWORK_NAME=$PRIVATE_NETWORK_NAME
@@ -439,10 +435,10 @@
         TEMPEST_VOLUME_MANAGE_SNAPSHOT=${TEMPEST_VOLUME_MANAGE_SNAPSHOT:-True}
     fi
     iniset $TEMPEST_CONFIG volume-feature-enabled manage_snapshot $(trueorfalse False TEMPEST_VOLUME_MANAGE_SNAPSHOT)
-    # TODO(ynesenenko): Remove the volume_services flag when Liberty and Kilo will correct work with host info.
-    iniset $TEMPEST_CONFIG volume-feature-enabled volume_services True
+
     # TODO(ameade): Remove the api_v3 flag when Mitaka and Liberty are end of life.
     iniset $TEMPEST_CONFIG volume-feature-enabled api_v3 True
+    iniset $TEMPEST_CONFIG volume-feature-enabled api_v1 $(trueorfalse False TEMPEST_VOLUME_API_V1)
     local tempest_volume_min_microversion=${TEMPEST_VOLUME_MIN_MICROVERSION:-None}
     local tempest_volume_max_microversion=${TEMPEST_VOLUME_MAX_MICROVERSION:-"latest"}
     if [ "$tempest_volume_min_microversion" == "None" ]; then
diff --git a/lib/tls b/lib/tls
index 57b5e52..f9ef554 100644
--- a/lib/tls
+++ b/lib/tls
@@ -519,6 +519,10 @@
     SSLEngine On
     SSLCertificateFile $DEVSTACK_CERT
 
+    # Disable KeepAlive to fix bug #1630664 a.k.a the
+    # ('Connection aborted.', BadStatusLine("''",)) error
+    KeepAlive Off
+
     <Location />
         ProxyPass http://$b_host:$b_port/ retry=5 nocanon
         ProxyPassReverse http://$b_host:$b_port/
diff --git a/openrc b/openrc
index d1c6129..483b5af 100644
--- a/openrc
+++ b/openrc
@@ -53,10 +53,6 @@
 # or NOVA_PASSWORD.
 export OS_PASSWORD=${ADMIN_PASSWORD:-secret}
 
-# Don't put the key into a keyring by default. Testing for development is much
-# easier with this off.
-export OS_NO_CACHE=${OS_NO_CACHE:-1}
-
 # Region
 export OS_REGION_NAME=${REGION_NAME:-RegionOne}
 
diff --git a/stack.sh b/stack.sh
index 7d440a7..94315e1 100755
--- a/stack.sh
+++ b/stack.sh
@@ -12,7 +12,7 @@
 # a multi-node developer install.
 
 # To keep this script simple we assume you are running on a recent **Ubuntu**
-# (14.04 Trusty or newer), **Fedora** (F20 or newer), or **CentOS/RHEL**
+# (16.04 Xenial or newer), **Fedora** (F24 or newer), or **CentOS/RHEL**
 # (7 or newer) machine. (It may work on other platforms but support for those
 # platforms is left to those who added them to DevStack.) It should work in
 # a VM or physical server. Additionally, we maintain a list of ``deb`` and
@@ -192,7 +192,7 @@
 
 # Warn users who aren't on an explicitly supported distro, but allow them to
 # override check and attempt installation with ``FORCE=yes ./stack``
-if [[ ! ${DISTRO} =~ (trusty|xenial|yakkety|7.0|wheezy|sid|testing|jessie|f23|f24|f25|rhel7|kvmibm1) ]]; then
+if [[ ! ${DISTRO} =~ (xenial|yakkety|zesty|sid|testing|jessie|f24|f25|rhel7|kvmibm1) ]]; then
     echo "WARNING: this script has not been tested on $DISTRO"
     if [[ "$FORCE" != "yes" ]]; then
         die $LINENO "If you wish to run this script anyway run with FORCE=yes"
@@ -872,7 +872,7 @@
 # if placement-api or placement-client is active, and n-cpu on the
 # same box.
 if is_service_enabled placement placement-client; then
-    if is_service_enabled n-cpu; then
+    if is_service_enabled n-cpu || is_service_enabled n-sch; then
         configure_placement_nova_compute
     fi
 fi
diff --git a/stackrc b/stackrc
index d8d0ee4..95f017b 100644
--- a/stackrc
+++ b/stackrc
@@ -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"
+
+# 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.
@@ -614,7 +624,7 @@
 #IMAGE_URLS="http://smoser.brickies.net/ubuntu/ttylinux-uec/ttylinux-uec-amd64-11.2_2.6.35-15_1.tar.gz" # old ttylinux-uec image
 #IMAGE_URLS="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-disk.img" # cirros full disk image
 
-CIRROS_VERSION=${CIRROS_VERSION:-"0.3.4"}
+CIRROS_VERSION=${CIRROS_VERSION:-"0.3.5"}
 CIRROS_ARCH=${CIRROS_ARCH:-"x86_64"}
 
 # Set default image based on ``VIRT_DRIVER`` and ``LIBVIRT_TYPE``, either of
@@ -634,9 +644,9 @@
                 lxc) # the cirros root disk in the uec tarball is empty, so it will not work for lxc
                     DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs}
                     IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs.img.gz";;
-                *) # otherwise, use the uec style image (with kernel, ramdisk, disk)
-                    DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
-                    IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz";;
+                *) # otherwise, use the qcow image
+                    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
             ;;
         vsphere)
@@ -650,9 +660,9 @@
             # NOTE(lucasagomes): The logic setting the default image
             # now lives in the Ironic tree
             ;;
-        *) # Default to Cirros with kernel, ramdisk and disk image
-            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
-            IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz";;
+        *) # 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/dstat.sh b/tools/dstat.sh
index 3c0b3be..1c80fb7 100755
--- a/tools/dstat.sh
+++ b/tools/dstat.sh
@@ -13,7 +13,7 @@
 LOGDIR=$1
 
 # Command line arguments for primary DStat process.
-DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv --swap"
+DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv --top-mem --swap"
 
 # Command-line arguments for secondary background DStat process.
 DSTAT_CSV_OPTS="-tcmndrylpg --output $LOGDIR/dstat-csv.log"
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
diff --git a/tools/worlddump.py b/tools/worlddump.py
index 1ce931e..eb109b9 100755
--- a/tools/worlddump.py
+++ b/tools/worlddump.py
@@ -17,6 +17,8 @@
 
 """Dump the state of the world for post mortem."""
 
+from __future__ import print_function
+
 import argparse
 import datetime
 from distutils import spawn
@@ -151,7 +153,11 @@
 def _netns_list():
     process = subprocess.Popen(['ip', 'netns'], stdout=subprocess.PIPE)
     stdout, _ = process.communicate()
-    return stdout.split()
+    # NOTE(jlvillal): Sometimes 'ip netns list' can return output like:
+    #   qrouter-0805fd7d-c493-4fa6-82ca-1c6c9b23cd9e (id: 1)
+    #   qdhcp-bb2cc6ae-2ae8-474f-adda-a94059b872b5 (id: 0)
+    output = [x.split()[0] for x in stdout.splitlines()]
+    return output
 
 
 def network_dump():
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index 25bf58c..34ef719 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -96,48 +96,27 @@
 tar xf /tmp/devstack.tar -C $STAGING_DIR/opt/stack/devstack
 cd $TOP_DIR
 
-# Create an upstart job (task) for devstack, which can interact with the console
-cat >$STAGING_DIR/etc/init/devstack.conf << EOF
-start on stopped rc RUNLEVEL=[2345]
+# Create an systemd task for devstack
+cat >$STAGING_DIR/etc/systemd/system/devstack.service << EOF
+[Unit]
+Description=Install OpenStack by DevStack
 
-console output
-task
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStartPre=/bin/rm -f /opt/stack/runsh.succeeded
+ExecStart=/bin/su -c "/opt/stack/run.sh" stack
+StandardOutput=tty
+StandardError=tty
 
-pre-start script
-    rm -f /opt/stack/runsh.succeeded
-end script
+[Install]
+WantedBy=multi-user.target
 
-script
-    initctl stop hvc0 || true
-
-    # Read any leftover characters from standard input
-    while read -n 1 -s -t 0.1 -r ignored; do
-        true
-    done
-
-    clear
-
-    chown -R $STACK_USER /opt/stack
-
-    su -c "/opt/stack/run.sh" $STACK_USER
-
-    # Update /etc/issue
-    {
-        echo "OpenStack VM - Installed by DevStack"
-        IPADDR=\$(ip -4 address show eth0 | sed -n 's/.*inet \\([0-9\.]\\+\\).*/\1/p')
-        echo "  Management IP:   \$IPADDR"
-        echo -n "  Devstack run:    "
-        if [ -e /opt/stack/runsh.succeeded ]; then
-            echo "SUCCEEDED"
-        else
-            echo "FAILED"
-        fi
-        echo ""
-    } > /etc/issue
-    initctl start hvc0 > /dev/null 2>&1
-end script
 EOF
 
+# enable this service
+ln -s $STAGING_DIR/etc/systemd/system/devstack.service $STAGING_DIR/etc/systemd/system/multi-user.target.wants/devstack.service
+
 # Configure the hostname
 echo $GUEST_NAME > $STAGING_DIR/etc/hostname
 
@@ -178,6 +157,8 @@
 (
   flock -n 9 || exit 1
 
+  sudo chown -R stack /opt/stack
+
   [ -e /opt/stack/runsh.succeeded ] && rm /opt/stack/runsh.succeeded
   echo \$\$ >> /opt/stack/run_sh.pid
 
@@ -187,7 +168,24 @@
 
   # Got to the end - success
   touch /opt/stack/runsh.succeeded
+
+  # Update /etc/issue
+  (
+      echo "OpenStack VM - Installed by DevStack"
+      IPADDR=$(ip -4 address show eth0 | sed -n 's/.*inet \([0-9\.]\+\).*/\1/p')
+      echo "  Management IP:   $IPADDR"
+      echo -n "  Devstack run:    "
+      if [ -e /opt/stack/runsh.succeeded ]; then
+          echo "SUCCEEDED"
+      else
+          echo "FAILED"
+      fi
+      echo ""
+  ) > /opt/stack/issue
+  sudo cp /opt/stack/issue /etc/issue
+
   rm /opt/stack/run_sh.pid
 ) 9> /opt/stack/.runsh_lock
 EOF
+
 chmod 755 $STAGING_DIR/opt/stack/run.sh
diff --git a/tools/xen/functions b/tools/xen/functions
index e1864eb..93f3413 100644
--- a/tools/xen/functions
+++ b/tools/xen/functions
@@ -317,7 +317,7 @@
         # Only support conntrack-tools in Dom0 with XS7.0 and above
         if [ ! -f /usr/sbin/conntrackd ]; then
             sed -i s/#baseurl=/baseurl=/g /etc/yum.repos.d/CentOS-Base.repo
-            centos_ver=$(yum version nogroups |grep Installed | cut -d' ' -f 2 | cut -d'.' -f1-2 | tr '-' '.')
+            centos_ver=$(yum version nogroups |grep Installed | cut -d' ' -f 2 | cut -d'/' -f 1 | cut -d'-' -f 1)
             yum install -y --enablerepo=base --releasever=$centos_ver conntrack-tools
             # Backup conntrackd.conf after install conntrack-tools, use the one with statistic mode
             mv /etc/conntrackd/conntrackd.conf /etc/conntrackd/conntrackd.conf.back
diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh
index 66b9eda..d2e2c57 100755
--- a/tools/xen/install_os_domU.sh
+++ b/tools/xen/install_os_domU.sh
@@ -424,7 +424,7 @@
     echo "looking at the console of your domU / checking the log files."
     echo ""
     echo "ssh into your domU now: 'ssh stack@$OS_VM_MANAGEMENT_ADDRESS' using your password"
-    echo "and then do: 'sudo service devstack status' to check if devstack is still running."
+    echo "and then do: 'sudo systemctl status devstack' to check if devstack is still running."
     echo "Check that /opt/stack/runsh.succeeded exists"
     echo ""
     echo "When devstack completes, you can visit the OpenStack Dashboard"
diff --git a/tools/xen/scripts/install_ubuntu_template.sh b/tools/xen/scripts/install_ubuntu_template.sh
index d80ed09..6ea3642 100755
--- a/tools/xen/scripts/install_ubuntu_template.sh
+++ b/tools/xen/scripts/install_ubuntu_template.sh
@@ -50,7 +50,7 @@
 # however these need to be answered before the netinstall
 # is ready to fetch the preseed file, and as such must be here
 # to get a fully automated install
-pvargs="-- quiet console=hvc0 partman/default_filesystem=ext3 \
+pvargs="quiet console=hvc0 partman/default_filesystem=ext3 \
 console-setup/ask_detect=false locale=${UBUNTU_INST_LOCALE} \
 keyboard-configuration/layoutcode=${UBUNTU_INST_KEYBOARD} \
 netcfg/choose_interface=eth0 \
diff --git a/tools/xen/xenrc b/tools/xen/xenrc
index 2161247..60be02f 100644
--- a/tools/xen/xenrc
+++ b/tools/xen/xenrc
@@ -63,8 +63,8 @@
 PUB_NETMASK=${PUB_NETMASK:-255.255.255.0}
 
 # Ubuntu install settings
-UBUNTU_INST_RELEASE="trusty"
-UBUNTU_INST_TEMPLATE_NAME="Ubuntu 14.04 (64-bit) for DevStack"
+UBUNTU_INST_RELEASE="xenial"
+UBUNTU_INST_TEMPLATE_NAME="Ubuntu 16.04 (64-bit) for DevStack"
 # For 12.04 use "precise" and update template name
 # However, for 12.04, you should be using
 # XenServer 6.1 and later or XCP 1.6 or later