Merge "XenAPI: Fix disk_formats verified by tempest"
diff --git a/clean.sh b/clean.sh
index ae28aa9..5da7851 100755
--- a/clean.sh
+++ b/clean.sh
@@ -50,7 +50,6 @@
 source $TOP_DIR/lib/swift
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/neutron-legacy
-source $TOP_DIR/lib/ironic
 
 
 # Extras Source
@@ -138,6 +137,7 @@
 FILES_TO_CLEAN+="docs/files docs/html shocco/ "
 FILES_TO_CLEAN+="stack-screenrc test*.conf* test.ini* "
 FILES_TO_CLEAN+=".stackenv .prereqs"
+FILES_TO_CLEAN+="/etc/openstack/ ~/.config/openstack"
 
 for file in $FILES_TO_CLEAN; do
     rm -rf $TOP_DIR/$file
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index d87809a..a7d3b7d 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -44,6 +44,7 @@
    before they are started
 -  **extra** - runs after services are started and before any files in
    ``extra.d`` are executed
+-  **post-extra** - runs after files in ``extra.d`` are executed
 
 The file is processed strictly in sequence; meta-sections may be
 specified more than once but if any settings are duplicated the last to
@@ -107,7 +108,6 @@
     DATABASE_PASSWORD=$ADMIN_PASSWORD
     RABBIT_PASSWORD=$ADMIN_PASSWORD
     SERVICE_PASSWORD=$ADMIN_PASSWORD
-    SERVICE_TOKEN=a682f596-76f3-11e3-b3b2-e716f9080d50
     #FIXED_RANGE=172.31.1.0/24
     #FLOATING_RANGE=192.168.20.0/25
     #HOST_IP=10.3.4.5
diff --git a/doc/source/guides/devstack-with-lbaas-v2.rst b/doc/source/guides/devstack-with-lbaas-v2.rst
index f3bd2fe..0c439ad 100644
--- a/doc/source/guides/devstack-with-lbaas-v2.rst
+++ b/doc/source/guides/devstack-with-lbaas-v2.rst
@@ -34,7 +34,6 @@
     DATABASE_PASSWORD=password
     ADMIN_PASSWORD=password
     SERVICE_PASSWORD=password
-    SERVICE_TOKEN=password
     RABBIT_PASSWORD=password
     # Enable Logging
     LOGFILE=$DEST/logs/stack.sh.log
@@ -46,7 +45,7 @@
     # Horizon
     ENABLED_SERVICES+=,horizon
     # Nova
-    ENABLED_SERVICES+=,n-api,n-crt,n-obj,n-cpu,n-cond,n-sch
+    ENABLED_SERVICES+=,n-api,n-crt,n-cpu,n-cond,n-sch
     # Glance
     ENABLED_SERVICES+=,g-api,g-reg
     # Neutron
diff --git a/doc/source/guides/multinode-lab.rst b/doc/source/guides/multinode-lab.rst
index 5660bc5..37c8515 100644
--- a/doc/source/guides/multinode-lab.rst
+++ b/doc/source/guides/multinode-lab.rst
@@ -131,7 +131,6 @@
     DATABASE_PASSWORD=supersecret
     RABBIT_PASSWORD=supersecrete
     SERVICE_PASSWORD=supersecrete
-    SERVICE_TOKEN=xyzpdqlazydog
 
 In the multi-node configuration the first 10 or so IPs in the private
 subnet are usually reserved. Add this to ``local.sh`` to have it run
@@ -172,7 +171,6 @@
     DATABASE_PASSWORD=supersecret
     RABBIT_PASSWORD=supersecrete
     SERVICE_PASSWORD=supersecrete
-    SERVICE_TOKEN=xyzpdqlazydog
     DATABASE_TYPE=mysql
     SERVICE_HOST=192.168.42.11
     MYSQL_HOST=$SERVICE_HOST
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 9dcb654..84295a5 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -59,7 +59,6 @@
         DATABASE_PASSWORD=secrete
         RABBIT_PASSWORD=secrete
         SERVICE_PASSWORD=secrete
-        SERVICE_TOKEN=secrete
 
         # Do not use Nova-Network
         disable_service n-net
@@ -231,7 +230,6 @@
     MYSQL_PASSWORD=secrete
     RABBIT_PASSWORD=secrete
     SERVICE_PASSWORD=secrete
-    SERVICE_TOKEN=secrete
 
     ## Neutron options
     PUBLIC_INTERFACE=eth0
@@ -362,7 +360,6 @@
         MYSQL_PASSWORD=secrete
         RABBIT_PASSWORD=secrete
         SERVICE_PASSWORD=secrete
-        SERVICE_TOKEN=secrete
 
         ## Neutron options
         Q_USE_SECGROUP=True
@@ -383,6 +380,7 @@
         ## Neutron Networking options used to create Neutron Subnets
 
         FIXED_RANGE="203.0.113.0/24"
+        NETWORK_GATEWAY=203.0.113.1
         PROVIDER_SUBNET_NAME="provider_net"
         PROVIDER_NETWORK_TYPE="vlan"
         SEGMENTATION_ID=2010
@@ -409,7 +407,6 @@
         MYSQL_PASSWORD=secrete
         RABBIT_PASSWORD=secrete
         SERVICE_PASSWORD=secrete
-        SERVICE_TOKEN=secrete
 
         # Services that a compute node runs
         ENABLED_SERVICES=n-cpu,rabbit,q-agt
diff --git a/doc/source/guides/single-machine.rst b/doc/source/guides/single-machine.rst
index a01c368..011c41f 100644
--- a/doc/source/guides/single-machine.rst
+++ b/doc/source/guides/single-machine.rst
@@ -108,7 +108,6 @@
     DATABASE_PASSWORD=iheartdatabases
     RABBIT_PASSWORD=flopsymopsy
     SERVICE_PASSWORD=iheartksl
-    SERVICE_TOKEN=xyzpdqlazydog
 
 Run DevStack:
 
diff --git a/doc/source/guides/single-vm.rst b/doc/source/guides/single-vm.rst
index 53c3fa9..45b8f2d 100644
--- a/doc/source/guides/single-vm.rst
+++ b/doc/source/guides/single-vm.rst
@@ -67,7 +67,6 @@
             echo DATABASE_PASSWORD=password >> local.conf
             echo RABBIT_PASSWORD=password >> local.conf
             echo SERVICE_PASSWORD=password >> local.conf
-            echo SERVICE_TOKEN=tokentoken >> local.conf
             ./stack.sh
         path: /home/stack/start.sh
         permissions: 0755
diff --git a/doc/source/index.rst b/doc/source/index.rst
index b65730f..4a1d93d 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -20,7 +20,7 @@
 
 #. Select a Linux Distribution
 
-   Only Ubuntu 14.04 (Trusty), Fedora 21 (or Fedora 22) and CentOS/RHEL
+   Only Ubuntu 14.04 (Trusty), Fedora 22 (or Fedora 23) and CentOS/RHEL
    7 are documented here. OpenStack also runs and is packaged on other
    flavors of Linux such as OpenSUSE and Debian.
 
@@ -44,6 +44,18 @@
 
    We recommend at least a :ref:`minimal-configuration` be set up.
 
+#. Add Stack User
+
+   Devstack should be run as a non-root user with sudo enabled
+   (standard logins to cloud images such as "ubuntu" or "cloud-user"
+   are usually fine).
+
+   You can quickly create a separate `stack` user to run DevStack with
+
+   ::
+
+       devstack/tools/create-stack-user.sh; su stack
+
 #. Start the install
 
    ::
@@ -162,7 +174,6 @@
 * `lib/heat <lib/heat.html>`__
 * `lib/horizon <lib/horizon.html>`__
 * `lib/infra <lib/infra.html>`__
-* `lib/ironic <lib/ironic.html>`__
 * `lib/keystone <lib/keystone.html>`__
 * `lib/ldap <lib/ldap.html>`__
 * `lib/neutron-legacy <lib/neutron-legacy.html>`__
@@ -177,7 +188,6 @@
 * `clean.sh <clean.sh.html>`__
 * `run\_tests.sh <run_tests.sh.html>`__
 
-* `extras.d/50-ironic.sh <extras.d/50-ironic.sh.html>`__
 * `extras.d/60-ceph.sh <extras.d/60-ceph.sh.html>`__
 * `extras.d/70-tuskar.sh <extras.d/70-tuskar.sh.html>`__
 * `extras.d/80-tempest.sh <extras.d/80-tempest.sh.html>`__
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 49b3a7f..b96883a 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -26,8 +26,14 @@
 +------------------+---------------------------------------------+--------------------+
 |ceilometer        |git://git.openstack.org/openstack/ceilometer | metering           |
 +------------------+---------------------------------------------+--------------------+
+|congress          |git://git.openstack.org/openstack/congress   | governance         |
++------------------+---------------------------------------------+--------------------+
+|cue               |git://git.openstack.org/openstack/cue        | message-broker     |
++------------------+---------------------------------------------+--------------------+
 |gnocchi           |git://git.openstack.org/openstack/gnocchi    | metric             |
 +------------------+---------------------------------------------+--------------------+
+|ironic            |git://git.openstack.org/openstack/ironic     | baremetal          |
++------------------+---------------------------------------------+--------------------+
 |magnum            |git://git.openstack.org/openstack/magnum     |                    |
 +------------------+---------------------------------------------+--------------------+
 |manila            |git://git.openstack.org/openstack/manila     | file shares        |
@@ -76,16 +82,30 @@
 Additional Services
 ===================
 
-+----------------+--------------------------------------------------+------------+
-| Plugin Name    | URL                                              | Comments   |
-|                |                                                  |            |
-+----------------+--------------------------------------------------+------------+
-|ec2-api         |git://git.openstack.org/openstack/ec2-api         |[as1]_      |
-+----------------+--------------------------------------------------+------------+
-|ironic-inspector|git://git.openstack.org/openstack/ironic-inspector|            |
-+----------------+--------------------------------------------------+------------+
-|                |                                                  |            |
-+----------------+--------------------------------------------------+------------+
++-----------------+------------------------------------------------------------+------------+
+| Plugin Name     | URL                                                        | Comments   |
+|                 |                                                            |            |
++-----------------+------------------------------------------------------------+------------+
+|amqp1            |git://git.openstack.org/openstack/devstack-plugin-amqp1     |            |
++-----------------+------------------------------------------------------------+------------+
+|bdd              |git://git.openstack.org/openstack/devstack-plugin-bdd       |            |
++-----------------+------------------------------------------------------------+------------+
+|ec2-api          |git://git.openstack.org/openstack/ec2-api                   |[as1]_      |
++-----------------+------------------------------------------------------------+------------+
+|glusterfs        |git://git.openstack.org/openstack/devstack-plugin-glusterfs |            |
++-----------------+------------------------------------------------------------+------------+
+|hdfs             |git://git.openstack.org/openstack/devstack-plugin-hdfs      |            |
++-----------------+------------------------------------------------------------+------------+
+|ironic-inspector |git://git.openstack.org/openstack/ironic-inspector          |            |
++-----------------+------------------------------------------------------------+------------+
+|pika             |git://git.openstack.org/openstack/devstack-plugin-pika      |            |
++-----------------+------------------------------------------------------------+------------+
+|sheepdog         |git://git.openstack.org/openstack/devstack-plugin-sheepdog  |            |
++-----------------+------------------------------------------------------------+------------+
+|zmq              |git://git.openstack.org/openstack/devstack-plugin-zmq       |            |
++-----------------+------------------------------------------------------------+------------+
+|                 |                                                            |            |
++-----------------+------------------------------------------------------------+------------+
 
 .. [as1] first functional devstack plugin, hence why used in most of
          the examples.
diff --git a/doc/source/plugins.rst b/doc/source/plugins.rst
index b8da7e1..83e5609 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -21,12 +21,12 @@
 An external git repository that includes a ``devstack/`` top level
 directory. Inside this directory there can be 3 files.
 
-- ``override_defaults`` - a file containing global variables that
+- ``override-defaults`` - a file containing global variables that
   will be sourced before the lib/* files. This allows the plugin
   to override the defaults that are otherwise set in the lib/*
   files.
 
-  For example, override_defaults may export CINDER_ENABLED_BACKENDS
+  For example, override-defaults may export CINDER_ENABLED_BACKENDS
   to include the plugin-specific storage backend and thus be able
   to override the default lvm only storage backend for Cinder.
 
diff --git a/doc/source/stackrc.rst b/doc/source/stackrc.rst
index b21f74f..81d4b80 100644
--- a/doc/source/stackrc.rst
+++ b/doc/source/stackrc.rst
@@ -20,7 +20,7 @@
 
     ::
 
-        ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,c-sch,c-api,c-vol,n-sch,n-cauth,horizon,rabbit,tempest,$DATABASE_TYPE
+        ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-cpu,n-net,n-cond,c-sch,c-api,c-vol,n-sch,n-cauth,horizon,rabbit,tempest,$DATABASE_TYPE
 
     Other services that are not enabled by default can be enabled in
     ``localrc``. For example, to add Swift, use the following service
diff --git a/extras.d/50-ironic.sh b/extras.d/50-ironic.sh
deleted file mode 100644
index 3b8e3d5..0000000
--- a/extras.d/50-ironic.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-# ironic.sh - Devstack extras script to install ironic
-
-if is_service_enabled ir-api ir-cond; then
-    if [[ "$1" == "source" ]]; then
-        # Initial source
-        source $TOP_DIR/lib/ironic
-    elif [[ "$1" == "stack" && "$2" == "install" ]]; then
-        echo_summary "Installing Ironic"
-        install_ironic
-        install_ironicclient
-        cleanup_ironic
-    elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
-        echo_summary "Configuring Ironic"
-        configure_ironic
-
-        if is_service_enabled key; then
-            create_ironic_accounts
-        fi
-
-    elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
-        # Initialize ironic
-        init_ironic
-
-        # Start the ironic API and ironic taskmgr components
-        echo_summary "Starting Ironic"
-        start_ironic
-
-        if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
-            prepare_baremetal_basic_ops
-        fi
-    fi
-
-    if [[ "$1" == "unstack" ]]; then
-        stop_ironic
-        if [[ "$IRONIC_BAREMETAL_BASIC_OPS" = "True" ]]; then
-            cleanup_baremetal_basic_ops
-        fi
-    fi
-
-    if [[ "$1" == "clean" ]]; then
-        cleanup_ironic
-    fi
-fi
diff --git a/extras.d/60-ceph.sh b/extras.d/60-ceph.sh
index 38b901b..cc90128 100644
--- a/extras.d/60-ceph.sh
+++ b/extras.d/60-ceph.sh
@@ -32,7 +32,7 @@
             echo_summary "Configuring Cinder for Ceph"
             configure_ceph_cinder
         fi
-        if is_service_enabled cinder || is_service_enabled nova; then
+        if is_service_enabled n-cpu; then
             # NOTE (leseb): the part below is a requirement to attach Ceph block devices
             echo_summary "Configuring libvirt secret"
             import_libvirt_secret_ceph
diff --git a/extras.d/80-tempest.sh b/extras.d/80-tempest.sh
index 74f4c60..5e8da99 100644
--- a/extras.d/80-tempest.sh
+++ b/extras.d/80-tempest.sh
@@ -13,7 +13,6 @@
     elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
         echo_summary "Initializing Tempest"
         configure_tempest
-        init_tempest
     elif [[ "$1" == "stack" && "$2" == "post-extra" ]]; then
         # local.conf Tempest option overrides
         :
diff --git a/files/apache-ironic.template b/files/apache-ironic.template
deleted file mode 100644
index 8864194..0000000
--- a/files/apache-ironic.template
+++ /dev/null
@@ -1,12 +0,0 @@
-Listen %PUBLICPORT%
-
-<VirtualHost *:%PUBLICPORT%>
-    DocumentRoot "%HTTPROOT%"
-    <Directory "%HTTPROOT%">
-        Options Indexes FollowSymLinks
-        AllowOverride None
-        Order allow,deny
-        Allow from all
-        Require all granted
-    </Directory>
-</VirtualHost>
diff --git a/files/apache-nova-ec2-api.template b/files/apache-nova-ec2-api.template
deleted file mode 100644
index 7b1d68b..0000000
--- a/files/apache-nova-ec2-api.template
+++ /dev/null
@@ -1,25 +0,0 @@
-Listen %PUBLICPORT%
-
-<VirtualHost *:%PUBLICPORT%>
-    WSGIDaemonProcess nova-ec2-api processes=%APIWORKERS% threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
-    WSGIProcessGroup nova-ec2-api
-    WSGIScriptAlias / %PUBLICWSGI%
-    WSGIApplicationGroup %{GLOBAL}
-    WSGIPassAuthorization On
-    <IfVersion >= 2.4>
-      ErrorLogFormat "%M"
-    </IfVersion>
-    ErrorLog /var/log/%APACHE_NAME%/nova-ec2-api.log
-    %SSLENGINE%
-    %SSLCERTFILE%
-    %SSLKEYFILE%
-</VirtualHost>
-
-Alias /ec2 %PUBLICWSGI%
-<Location /ec2>
-    SetHandler wsgi-script
-    Options +ExecCGI
-    WSGIProcessGroup nova-ec2-api
-    WSGIApplicationGroup %{GLOBAL}
-    WSGIPassAuthorization On
-</Location>
diff --git a/files/debs/ironic b/files/debs/ironic
deleted file mode 100644
index 4d5a6aa..0000000
--- a/files/debs/ironic
+++ /dev/null
@@ -1,19 +0,0 @@
-docker.io
-ipmitool
-iptables
-ipxe
-libguestfs0
-libvirt-bin
-open-iscsi
-openssh-client
-openvswitch-datapath-dkms
-openvswitch-switch
-python-libguestfs
-python-libvirt
-qemu
-qemu-kvm
-qemu-utils
-sgabios
-syslinux
-tftpd-hpa
-xinetd
diff --git a/files/debs/keystone b/files/debs/keystone
index 0795167..370e4aa 100644
--- a/files/debs/keystone
+++ b/files/debs/keystone
@@ -1,6 +1,5 @@
 libkrb5-dev
 libldap2-dev
 libsasl2-dev
-python-mysql.connector
 python-mysqldb
 sqlite3
diff --git a/files/debs/neutron b/files/debs/neutron
index 85145d3..e53cc68 100644
--- a/files/debs/neutron
+++ b/files/debs/neutron
@@ -8,7 +8,6 @@
 libmysqlclient-dev
 mysql-server #NOPRIME
 postgresql-server-dev-all
-python-mysql.connector
 python-mysqldb
 rabbitmq-server # NOPRIME
 radvd # NOPRIME
diff --git a/files/debs/nova b/files/debs/nova
index fe57fc4..58dad41 100644
--- a/files/debs/nova
+++ b/files/debs/nova
@@ -15,7 +15,6 @@
 mysql-server # NOPRIME
 parted
 pm-utils
-python-mysql.connector
 python-mysqldb
 qemu # dist:wheezy,jessie NOPRIME
 qemu-kvm # NOPRIME
diff --git a/files/rpms/general b/files/rpms/general
index 2804682..5bc87b6 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -8,9 +8,9 @@
 gettext  # used for compiling message catalogs
 git-core
 graphviz # needed only for docs
-iptables-services  # NOPRIME f21,f22,f23
+iptables-services  # NOPRIME f22,f23
 java-1.7.0-openjdk-headless  # NOPRIME rhel7
-java-1.8.0-openjdk-headless  # NOPRIME f21,f22,f23
+java-1.8.0-openjdk-headless  # NOPRIME f22,f23
 libffi-devel
 libjpeg-turbo-devel # Pillow 3.0.0
 libxml2-devel # lxml
@@ -26,7 +26,7 @@
 psmisc
 pyOpenSSL # version in pip uses too much memory
 python-devel
-redhat-rpm-config # MySQL-python rhbz-1195207 f21
+redhat-rpm-config # MySQL-python rhbz-1195207
 screen
 tar
 tcpdump
diff --git a/files/rpms/ironic b/files/rpms/ironic
deleted file mode 100644
index 2bf8bb3..0000000
--- a/files/rpms/ironic
+++ /dev/null
@@ -1,14 +0,0 @@
-docker-io
-ipmitool
-iptables
-ipxe-bootimgs
-libguestfs
-libvirt
-libvirt-python
-net-tools
-openssh-clients
-openvswitch
-sgabios
-syslinux
-tftp-server
-xinetd
diff --git a/files/rpms/neutron b/files/rpms/neutron
index 9683475..2e49a0c 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -4,7 +4,6 @@
 ebtables
 iptables
 iputils
-mysql-connector-python
 mysql-devel
 MySQL-python
 mysql-server # NOPRIME
diff --git a/files/rpms/nova b/files/rpms/nova
index 00e7596..0312e85 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -7,7 +7,7 @@
 genisoimage # required for config_drive
 iptables
 iputils
-kernel-modules # dist:f21,f22,f23
+kernel-modules # dist:f22,f23
 kpartx
 kvm # NOPRIME
 libvirt-bin # NOPRIME
@@ -15,7 +15,6 @@
 libvirt-python # NOPRIME
 libxml2-python
 m2crypto
-mysql-connector-python
 mysql-devel
 MySQL-python
 mysql-server # NOPRIME
diff --git a/functions b/functions
index 34da1ba..9495710 100644
--- a/functions
+++ b/functions
@@ -22,7 +22,7 @@
 source ${FUNC_DIR}/inc/rootwrap
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_FUNCTIONS=$(set +o | grep xtrace)
 set +o xtrace
 
 # Check if a function already exists
@@ -357,7 +357,9 @@
 function wait_for_service {
     local timeout=$1
     local url=$2
+    time_start "wait_for_service"
     timeout $timeout sh -c "while ! $CURL_GET -k --noproxy '*' -s $url >/dev/null; do sleep 1; done"
+    time_stop "wait_for_service"
 }
 
 
@@ -603,7 +605,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_FUNCTIONS
 
 # Local variables:
 # mode: shell-script
diff --git a/functions-common b/functions-common
index 6a065ba..47276f0 100644
--- a/functions-common
+++ b/functions-common
@@ -32,7 +32,7 @@
 #
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_FUNCTIONS_COMMON=$(set +o | grep xtrace)
 set +o xtrace
 
 # ensure we don't re-source this in the same environment
@@ -410,6 +410,8 @@
         DISTRO="rhel${os_RELEASE::1}"
     elif [[ "$os_VENDOR" =~ (XenServer) ]]; then
         DISTRO="xs$os_RELEASE"
+    elif [[ "$os_VENDOR" =~ (kvmibm) ]]; then
+        DISTRO="${os_VENDOR}${os_RELEASE::1}"
     else
         # Catch-all for now is Vendor + Release + Update
         DISTRO="$os_VENDOR-$os_RELEASE.$os_UPDATE"
@@ -444,7 +446,7 @@
 
     [ "$os_VENDOR" = "Fedora" ] || [ "$os_VENDOR" = "Red Hat" ] || \
         [ "$os_VENDOR" = "CentOS" ] || [ "$os_VENDOR" = "OracleLinux" ] || \
-        [ "$os_VENDOR" = "CloudLinux" ]
+        [ "$os_VENDOR" = "CloudLinux" ] || [ "$os_VENDOR" = "kvmibm" ]
 }
 
 
@@ -597,6 +599,7 @@
         timeout=${GIT_TIMEOUT}
     fi
 
+    time_start "git_timed"
     until timeout -s SIGINT ${timeout} git "$@"; do
         # 124 is timeout(1)'s special return code when it reached the
         # timeout; otherwise assume fatal failure
@@ -611,6 +614,7 @@
         fi
         sleep 5
     done
+    time_stop "git_timed"
 }
 
 # git update using reference as a branch.
@@ -866,6 +870,64 @@
     echo $user_role_id
 }
 
+# Gets or adds user role to domain
+# Usage: get_or_add_user_domain_role <role> <user> <domain>
+function get_or_add_user_domain_role {
+    local user_role_id
+    # Gets user role id
+    user_role_id=$(openstack role list \
+        --user $2 \
+        --column "ID" \
+        --domain $3 \
+        --column "Name" \
+        | grep " $1 " | get_field 1)
+    if [[ -z "$user_role_id" ]]; then
+        # Adds role to user and get it
+        openstack role add $1 \
+            --user $2 \
+            --domain $3
+        user_role_id=$(openstack role list \
+            --user $2 \
+            --column "ID" \
+            --domain $3 \
+            --column "Name" \
+            | grep " $1 " | get_field 1)
+    fi
+    echo $user_role_id
+}
+
+# Gets or adds user role to domain
+# Usage: get_or_add_user_domain_role <role> <user> <domain>
+function get_or_add_user_domain_role {
+    local user_role_id
+    # Gets user role id
+    user_role_id=$(openstack role list \
+        --user $2 \
+        --os-url=$KEYSTONE_SERVICE_URI_V3 \
+        --os-identity-api-version=3 \
+        --column "ID" \
+        --domain $3 \
+        --column "Name" \
+        | grep " $1 " | get_field 1)
+    if [[ -z "$user_role_id" ]]; then
+        # Adds role to user and get it
+        openstack role add $1 \
+            --user $2 \
+            --domain $3 \
+            --os-url=$KEYSTONE_SERVICE_URI_V3 \
+            --os-identity-api-version=3
+        user_role_id=$(openstack role list \
+            --user $2 \
+            --os-url=$KEYSTONE_SERVICE_URI_V3 \
+            --os-identity-api-version=3 \
+            --column "ID" \
+            --domain $3 \
+            --column "Name" \
+            | grep " $1 " | get_field 1)
+    fi
+    echo $user_role_id
+}
+
 # Gets or adds group role to project
 # Usage: get_or_add_group_project_role <role> <group> <project>
 function get_or_add_group_project_role {
@@ -949,11 +1011,18 @@
 function get_endpoint_url {
     echo $(openstack endpoint list \
             --service $1 --interface $2 \
-            --os-url $KEYSTONE_SERVICE_URI_V3 \
-            --os-identity-api-version=3 \
             -c URL -f value)
 }
 
+# check if we are using ironic with hardware
+# TODO(jroll) this is a kludge left behind when ripping ironic code
+# out of tree, as it is used by nova and neutron.
+# figure out a way to refactor nova/neutron code to eliminate this
+function is_ironic_hardware {
+    is_service_enabled ironic && [[ -n "${IRONIC_DEPLOY_DRIVER##*_ssh}" ]] && return 0
+    return 1
+}
+
 
 # Package Functions
 # =================
@@ -978,11 +1047,39 @@
     echo "$pkg_dir"
 }
 
+# Wrapper for ``apt-get update`` to try multiple times on the update
+# to address bad package mirrors (which happen all the time).
+function apt_get_update {
+    # only do this once per run
+    if [[ "$REPOS_UPDATED" == "True" && "$RETRY_UPDATE" != "True" ]]; then
+        return
+    fi
+
+    # bail if we are offline
+    [[ "$OFFLINE" = "True" ]] && return
+
+    local sudo="sudo"
+    [[ "$(id -u)" = "0" ]] && sudo="env"
+
+    # time all the apt operations
+    time_start "apt-get-update"
+
+    local proxies="http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} no_proxy=${no_proxy:-} "
+    local update_cmd="$sudo $proxies apt-get update"
+    if ! timeout 300 sh -c "while ! $update_cmd; do sleep 30; done"; then
+        die $LINENO "Failed to update apt repos, we're dead now"
+    fi
+
+    REPOS_UPDATED=True
+    # stop the clock
+    time_stop "apt-get-update"
+}
+
 # Wrapper for ``apt-get`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``*_proxy``
 # apt_get operation package [package ...]
 function apt_get {
-    local xtrace
+    local xtrace result
     xtrace=$(set +o | grep xtrace)
     set +o xtrace
 
@@ -998,10 +1095,12 @@
     $sudo DEBIAN_FRONTEND=noninteractive \
         http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \
         no_proxy=${no_proxy:-} \
-        apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
+        apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@" < /dev/null
+    result=$?
 
     # stop the clock
     time_stop "apt-get"
+    return $result
 }
 
 function _parse_package_files {
@@ -1139,7 +1238,7 @@
     local package_dir=""
     for plugin in ${DEVSTACK_PLUGINS//,/ }; do
         local package_dir="$(_get_package_dir ${GITDIR[$plugin]}/devstack/files)"
-        files_to_parse+="$package_dir/$plugin"
+        files_to_parse+=" $package_dir/$plugin"
     done
     echo "$(_parse_package_files $files_to_parse)"
     $xtrace
@@ -1158,16 +1257,7 @@
     fi
 
     if is_ubuntu; then
-        local xtrace
-        xtrace=$(set +o | grep xtrace)
-        set +o xtrace
-        if [[ "$REPOS_UPDATED" != "True" || "$RETRY_UPDATE" = "True" ]]; then
-            # if there are transient errors pulling the updates, that's fine.
-            # It may be secondary repositories that we don't really care about.
-            apt_get update  || /bin/true
-            REPOS_UPDATED=True
-        fi
-        $xtrace
+        apt_get_update
     fi
 }
 
@@ -1187,7 +1277,9 @@
 # install_package package [package ...]
 function install_package {
     update_package_repo
-    real_install_package $@ || RETRY_UPDATE=True update_package_repo && real_install_package $@
+    if ! real_install_package "$@"; then
+        RETRY_UPDATE=True update_package_repo && real_install_package "$@"
+    fi
 }
 
 # Distro-agnostic function to tell if a package is installed
@@ -1290,10 +1382,11 @@
     exec 3>&-
     exec 6>&-
 
-    local real_logfile="${LOGDIR}/${service}.log.${CURRENT_LOG_TIME}"
+    local logfile="${service}.log.${CURRENT_LOG_TIME}"
+    local real_logfile="${LOGDIR}/${logfile}"
     if [[ -n ${LOGDIR} ]]; then
         exec 1>&"$real_logfile" 2>&1
-        ln -sf "$real_logfile" ${LOGDIR}/${service}.log
+        bash -c "cd '$LOGDIR' && ln -sf '$logfile' ${service}.log"
         if [[ -n ${SCREEN_LOGDIR} ]]; then
             # Drop the backward-compat symlink
             ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${service}.log
@@ -1354,6 +1447,7 @@
     local command="$2"
     local group=$3
 
+    time_start "run_process"
     if is_service_enabled $service; then
         if [[ "$USE_SCREEN" = "True" ]]; then
             screen_process "$service" "$command" "$group"
@@ -1362,6 +1456,7 @@
             _run_process "$service" "$command" "$group" &
         fi
     fi
+    time_stop "run_process"
 }
 
 # Helper to launch a process in a named screen
@@ -1380,7 +1475,8 @@
 
     screen -S $SCREEN_NAME -X screen -t $name
 
-    local real_logfile="${LOGDIR}/${name}.log.${CURRENT_LOG_TIME}"
+    local logfile="${name}.log.${CURRENT_LOG_TIME}"
+    local real_logfile="${LOGDIR}/${logfile}"
     echo "LOGDIR: $LOGDIR"
     echo "SCREEN_LOGDIR: $SCREEN_LOGDIR"
     echo "log: $real_logfile"
@@ -1391,7 +1487,7 @@
         fi
         # If logging isn't active then avoid a broken symlink
         touch "$real_logfile"
-        ln -sf "$real_logfile" ${LOGDIR}/${name}.log
+        bash -c "cd '$LOGDIR' && ln -sf '$logfile' ${name}.log"
         if [[ -n ${SCREEN_LOGDIR} ]]; then
             # Drop the backward-compat symlink
             ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${1}.log
@@ -1741,17 +1837,18 @@
     if [[ -d $TOP_DIR/extras.d ]]; then
         local extra_plugin_file_name
         for extra_plugin_file_name in $TOP_DIR/extras.d/*.sh; do
-            [[ -r $extra_plugin_file_name ]] && source $extra_plugin_file_name $mode $phase
-            # NOTE(sdague): generate a big warning about using
-            # extras.d in an unsupported way which will let us track
-            # unsupported usage in the gate.
-            local exceptions="50-ironic.sh 60-ceph.sh 80-tempest.sh"
+            # NOTE(sdague): only process extras.d for the 3 explicitly
+            # white listed elements in tree. We want these to move out
+            # over time as well, but they are in tree, so we need to
+            # manage that.
+            local exceptions="60-ceph.sh 80-tempest.sh"
             local extra
             extra=$(basename $extra_plugin_file_name)
             if [[ ! ( $exceptions =~ "$extra" ) ]]; then
-                deprecated "extras.d support is being removed in Mitaka-1"
-                deprecated "jobs for project $extra will break after that point"
-                deprecated "please move project to a supported devstack plugin model"
+                warn "use of extras.d is no longer supported"
+                warn "processing of project $extra is skipped"
+            else
+                [[ -r $extra_plugin_file_name ]] && source $extra_plugin_file_name $mode $phase
             fi
         done
     fi
@@ -1932,7 +2029,6 @@
         [[ ${service} == n-cpu-* && ${ENABLED_SERVICES} =~ "n-cpu" ]] && enabled=0
         [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && enabled=0
         [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && enabled=0
-        [[ ${service} == "ironic" && ${ENABLED_SERVICES} =~ "ir-" ]] && enabled=0
         [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && enabled=0
         [[ ${service} == "trove" && ${ENABLED_SERVICES} =~ "tr-" ]] && enabled=0
         [[ ${service} == "swift" && ${ENABLED_SERVICES} =~ "s-" ]] && enabled=0
@@ -2176,9 +2272,11 @@
     local until=${3:-10}
     local sleep=${4:-0.5}
 
+    time_start "test_with_retry"
     if ! timeout $until sh -c "while ! $testcmd; do sleep $sleep; done"; then
         die $LINENO "$failmsg"
     fi
+    time_stop "test_with_retry"
 }
 
 # Timing infrastructure - figure out where large blocks of time are
@@ -2254,7 +2352,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_FUNCTIONS_COMMON
 
 # Local variables:
 # mode: shell-script
diff --git a/inc/ini-config b/inc/ini-config
index 42a66c6..e99b088 100644
--- a/inc/ini-config
+++ b/inc/ini-config
@@ -205,7 +205,7 @@
 }
 
 # Set a multiple line option in an INI file
-# iniset_multiline [-sudo] config-file section option value1 value2 valu3 ...
+# iniset_multiline [-sudo] config-file section option value1 value2 value3 ...
 function iniset_multiline {
     local xtrace
     xtrace=$(set +o | grep xtrace)
@@ -261,6 +261,18 @@
     $xtrace
 }
 
+# Get list of sections from an INI file
+# iniget_sections config-file
+function iniget_sections {
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
+    set +o xtrace
+    local file=$1
+
+    echo $(sed -ne "s/^\[\(.*\)\]/\1/p" "$file")
+    $xtrace
+}
+
 # Restore xtrace
 $INC_CONF_TRACE
 
diff --git a/inc/meta-config b/inc/meta-config
index b9ab6b2..6eb7a00 100644
--- a/inc/meta-config
+++ b/inc/meta-config
@@ -20,7 +20,7 @@
 # file-name is the destination of the config file
 
 # Save trace setting
-INC_META_XTRACE=$(set +o | grep xtrace)
+_XTRACE_INC_META=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -195,9 +195,28 @@
     done
 }
 
+function extract_localrc_section {
+    local configfile=$1    # top_dir/local.conf
+    local localrcfile=$2   # top_dir/localrc
+    local localautofile=$3 # top_dir/.localrc.auto
+
+    if [[ -r $configfile ]]; then
+        LRC=$(get_meta_section_files $configfile local)
+        for lfile in $LRC; do
+            if [[ "$lfile" == "localrc" ]]; then
+                if [[ -r $localrcfile ]]; then
+                    echo "localrc and local.conf:[[local]] both exist, using localrc"
+                else
+                    echo "# Generated file, do not edit" >$localautofile
+                    get_meta_section $configfile local $lfile >>$localautofile
+                fi
+            fi
+        done
+    fi
+}
 
 # Restore xtrace
-$INC_META_XTRACE
+$_XTRACE_INC_META
 
 # Local variables:
 # mode: shell-script
diff --git a/inc/python b/inc/python
index 91ceb44..35bab6f 100644
--- a/inc/python
+++ b/inc/python
@@ -17,7 +17,7 @@
 
 # Global Config Variables
 
-# PROJECT_VENV contains the name of the virtual enviromnet for each
+# 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
 
@@ -28,14 +28,17 @@
 # Get the path to the pip command.
 # get_pip_command
 function get_pip_command {
-    which pip || which pip-python
+    local version="$1"
+    # NOTE(dhellmann): I don't know if we actually get a pip3.4-python
+    # under any circumstances.
+    which pip${version} || which pip${version}-python
 
     if [ $? -ne 0 ]; then
-        die $LINENO "Unable to find pip; cannot continue"
+        die $LINENO "Unable to find pip${version}; cannot continue"
     fi
 }
 
-# Get the path to the direcotry where python executables are installed.
+# Get the path to the directory where python executables are installed.
 # get_python_exec_prefix
 function get_python_exec_prefix {
     local xtrace
@@ -66,12 +69,19 @@
     pip_install $clean_name
 }
 
+# Determine the python versions supported by a package
+function get_python_versions_for_package {
+    local name=$1
+    cd $name && python setup.py --classifiers \
+        | grep 'Language' | cut -f5 -d: | grep '\.' | tr '\n' ' '
+}
+
 # Wrapper for ``pip install`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
 # ``PIP_UPGRADE``, ``TRACK_DEPENDS``, ``*_proxy``,
 # pip_install package [package ...]
 function pip_install {
-    local xtrace
+    local xtrace result
     xtrace=$(set +o | grep xtrace)
     set +o xtrace
     local upgrade=""
@@ -93,7 +103,7 @@
     fi
     if [[ $TRACK_DEPENDS = True && ! "$@" =~ virtualenv ]]; then
         # TRACK_DEPENDS=True installation creates a circular dependency when
-        # we attempt to install virtualenv into a virualenv, so we must global
+        # we attempt to install virtualenv into a virtualenv, so we must global
         # that installation.
         source $DEST/.venv/bin/activate
         local cmd_pip=$DEST/.venv/bin/pip
@@ -104,8 +114,22 @@
             local sudo_pip="env"
         else
             local cmd_pip
-            cmd_pip=$(get_pip_command)
+            cmd_pip=$(get_pip_command $PYTHON2_VERSION)
             local sudo_pip="sudo -H"
+            if python3_enabled; then
+                # Look at the package classifiers to find the python
+                # versions supported, and if we find the version of
+                # python3 we've been told to use, use that instead of the
+                # default pip
+                local package_dir=${!#}
+                local python_versions
+                if [[ -d "$package_dir" ]]; then
+                    python_versions=$(get_python_versions_for_package $package_dir)
+                    if [[ $python_versions =~ $PYTHON3_VERSION ]]; then
+                        cmd_pip=$(get_pip_command $PYTHON3_VERSION)
+                    fi
+                fi
+            fi
         fi
     fi
 
@@ -113,6 +137,8 @@
     # Always apply constraints
     cmd_pip="$cmd_pip -c $REQUIREMENTS_DIR/upper-constraints.txt"
 
+    # FIXME(dhellmann): Need to force multiple versions of pip for
+    # packages like setuptools?
     local pip_version
     pip_version=$(python -c "import pip; \
                         print(pip.__version__.strip('.')[0])")
@@ -129,10 +155,11 @@
         PIP_FIND_LINKS=$PIP_FIND_LINKS \
         $cmd_pip $upgrade \
         $@
+    result=$?
 
     # Also install test requirements
     local test_req="${!#}/test-requirements.txt"
-    if [[ -e "$test_req" ]]; then
+    if [[ $result == 0 ]] && [[ -e "$test_req" ]]; then
         echo "Installing test-requirements for $test_req"
         $sudo_pip \
             http_proxy=${http_proxy:-} \
@@ -141,9 +168,11 @@
             PIP_FIND_LINKS=$PIP_FIND_LINKS \
             $cmd_pip $upgrade \
             -r $test_req
+        result=$?
     fi
 
     time_stop "pip_install"
+    return $result
 }
 
 # get version of a package from global requirements file
@@ -199,7 +228,7 @@
     setup_install $dir
 }
 
-# setup a library by name in editiable mode. If we are trying to use
+# setup a library by name in editable mode. If we are trying to use
 # the library from git, we'll do a git based install, otherwise we'll
 # punt and the library should be installed by a requirements pull from
 # another project.
@@ -213,15 +242,31 @@
 
 # this should be used if you want to install globally, all libraries should
 # use this, especially *oslo* ones
+#
+# setup_install project_dir [extras]
+# project_dir: directory of project repo (e.g., /opt/stack/keystone)
+# extras: comma-separated list of optional dependencies to install
+#         (e.g., ldap,memcache).
+#         See http://docs.openstack.org/developer/pbr/#extra-requirements
+# The command is like "pip install <project_dir>[<extras>]"
 function setup_install {
     local project_dir=$1
-    setup_package_with_constraints_edit $project_dir
+    local extras=$2
+    _setup_package_with_constraints_edit $project_dir "" $extras
 }
 
 # this should be used for projects which run services, like all services
+#
+# setup_develop project_dir [extras]
+# project_dir: directory of project repo (e.g., /opt/stack/keystone)
+# extras: comma-separated list of optional dependencies to install
+#         (e.g., ldap,memcache).
+#         See http://docs.openstack.org/developer/pbr/#extra-requirements
+# The command is like "pip install -e <project_dir>[<extras>]"
 function setup_develop {
     local project_dir=$1
-    setup_package_with_constraints_edit $project_dir -e
+    local extras=$2
+    _setup_package_with_constraints_edit $project_dir -e $extras
 }
 
 # determine if a project as specified by directory is in
@@ -243,10 +288,17 @@
 # install this package we get the from source version.
 #
 # Uses globals ``REQUIREMENTS_DIR``
-# setup_develop directory
-function setup_package_with_constraints_edit {
+# _setup_package_with_constraints_edit project_dir flags [extras]
+# project_dir: directory of project repo (e.g., /opt/stack/keystone)
+# flags: pip CLI options/flags
+# extras: comma-separated list of optional dependencies to install
+#         (e.g., ldap,memcache).
+#         See http://docs.openstack.org/developer/pbr/#extra-requirements
+# The command is like "pip install <flags> <project_dir>[<extras>]"
+function _setup_package_with_constraints_edit {
     local project_dir=$1
     local flags=$2
+    local extras=$3
 
     if [ -n "$REQUIREMENTS_DIR" ]; then
         # Constrain this package to this project directory from here on out.
@@ -257,25 +309,59 @@
             "$flags file://$project_dir#egg=$name"
     fi
 
-    setup_package $project_dir $flags
+    setup_package $project_dir "$flags" $extras
 
 }
 
 # ``pip install -e`` the package, which processes the dependencies
 # using pip before running `setup.py develop`
+#
 # Uses globals ``STACK_USER``
-# setup_develop_no_requirements_update directory
+# setup_package project_dir [flags] [extras]
+# project_dir: directory of project repo (e.g., /opt/stack/keystone)
+# flags: pip CLI options/flags
+# extras: comma-separated list of optional dependencies to install
+#         (e.g., ldap,memcache).
+#         See http://docs.openstack.org/developer/pbr/#extra-requirements
+# The command is like "pip install <flags> <project_dir>[<extras>]"
 function setup_package {
     local project_dir=$1
     local flags=$2
+    local extras=$3
 
-    pip_install $flags $project_dir
+    # if the flags variable exists, and it doesn't look like a flag,
+    # assume it's actually the extras list.
+    if [[ -n "$flags" && -z "$extras" && ! "$flags" =~ ^-.* ]]; then
+        extras=$flags
+        flags=""
+    fi
+
+    if [[ ! -z "$extras" ]]; then
+        extras="[$extras]"
+    fi
+
+    pip_install $flags "$project_dir$extras"
     # ensure that further actions can do things like setup.py sdist
     if [[ "$flags" == "-e" ]]; then
         safe_chown -R $STACK_USER $1/*.egg-info
     fi
 }
 
+# Report whether python 3 should be used
+function python3_enabled {
+    if [[ $USE_PYTHON3 == "True" ]]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+# Install python3 packages
+function install_python3 {
+    if is_ubuntu; then
+        apt_get install python3.4 python3.4-dev
+    fi
+}
 
 # Restore xtrace
 $INC_PY_TRACE
diff --git a/inc/rootwrap b/inc/rootwrap
index 63ab59a..2a6e4b6 100644
--- a/inc/rootwrap
+++ b/inc/rootwrap
@@ -22,14 +22,14 @@
     local line
 
     # This is pretty simplistic for now - assume only the first line is used
-    if [[ -r SUDO_SECURE_PATH_FILE ]]; then
+    if [[ -r $SUDO_SECURE_PATH_FILE ]]; then
         line=$(head -1 $SUDO_SECURE_PATH_FILE)
     else
         line="Defaults:$STACK_USER secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin"
     fi
 
     # Only add ``dir`` if it is not already present
-    if [[ $line =~ $dir ]]; then
+    if [[ ! $line =~ $dir ]]; then
         echo "${line}:$dir" | sudo tee $SUDO_SECURE_PATH_FILE
         sudo chmod 400 $SUDO_SECURE_PATH_FILE
         sudo chown root:root $SUDO_SECURE_PATH_FILE
diff --git a/lib/apache b/lib/apache
index 17526c7..2c84c7a 100644
--- a/lib/apache
+++ b/lib/apache
@@ -19,7 +19,7 @@
 # - restart_apache_server
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_APACHE=$(set +o | grep xtrace)
 set +o xtrace
 
 # Allow overriding the default Apache user and group, default to
@@ -185,13 +185,15 @@
     # Apache can be slow to stop, doing an explicit stop, sleep, start helps
     # to mitigate issues where apache will claim a port it's listening on is
     # still in use and fail to start.
+    time_start "restart_apache_server"
     stop_service $APACHE_NAME
     sleep 3
     start_service $APACHE_NAME
+    time_stop "restart_apache_server"
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_APACHE
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/ceph b/lib/ceph
index f573136..3e0839a 100644
--- a/lib/ceph
+++ b/lib/ceph
@@ -18,7 +18,7 @@
 # - cleanup_ceph
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_CEPH=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -116,7 +116,7 @@
 
 # check_os_support_ceph() - Check if the operating system provides a decent version of Ceph
 function check_os_support_ceph {
-    if [[ ! ${DISTRO} =~ (trusty|f21|f22|f23) ]]; then
+    if [[ ! ${DISTRO} =~ (trusty|f22|f23) ]]; then
         echo "WARNING: your distro $DISTRO does not provide (at least) the Firefly release. Please use Ubuntu Trusty or Fedora 20 (and higher)"
         if [[ "$FORCE_CEPH_INSTALL" != "yes" ]]; then
             die $LINENO "If you wish to install Ceph on this distribution anyway run with FORCE_CEPH_INSTALL=yes"
@@ -375,7 +375,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_CEPH
 
 ## Local variables:
 ## mode: shell-script
diff --git a/lib/cinder b/lib/cinder
index 1307c11..9ca8109 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -20,7 +20,7 @@
 # - cleanup_cinder
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -270,10 +270,6 @@
     iniset $CINDER_CONF DEFAULT state_path $CINDER_STATE_PATH
     iniset $CINDER_CONF oslo_concurrency lock_path $CINDER_STATE_PATH
     iniset $CINDER_CONF DEFAULT periodic_interval $CINDER_PERIODIC_INTERVAL
-    # NOTE(thingee): Cinder V1 API is deprecated and defaults to off as of
-    # Juno. Keep it enabled so we can continue testing while it's still
-    # supported.
-    iniset $CINDER_CONF DEFAULT enable_v1_api true
 
     iniset $CINDER_CONF DEFAULT os_region_name "$REGION_NAME"
 
@@ -309,6 +305,8 @@
     if is_service_enabled tls-proxy; then
         # Set the service port for a proxy to take the original
         iniset $CINDER_CONF DEFAULT osapi_volume_listen_port $CINDER_SERVICE_PORT_INT
+
+        iniset $CINDER_CONF DEFAULT public_endpoint $CINDER_SERVICE_PROTOCOL://$CINDER_SERVICE_HOST:$CINDER_SERVICE_PORT
     fi
 
     if [ "$SYSLOG" != "False" ]; then
@@ -355,7 +353,7 @@
     iniset $CINDER_CONF DEFAULT os_privileged_user_name nova
     iniset $CINDER_CONF DEFAULT os_privileged_user_password "$SERVICE_PASSWORD"
     iniset $CINDER_CONF DEFAULT os_privileged_user_tenant "$SERVICE_TENANT_NAME"
-
+    iniset $CINDER_CONF DEFAULT graceful_shutdown_timeout "$SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT"
 }
 
 # create_cinder_accounts() - Set up common required cinder accounts
@@ -469,6 +467,8 @@
 function _configure_tgt_for_config_d {
     if [[ ! -d /etc/tgt/stack.d/ ]]; then
         sudo ln -sf $CINDER_STATE_PATH/volumes /etc/tgt/stack.d
+    fi
+    if ! grep -q "include /etc/tgt/stack.d/*" /etc/tgt/targets.conf; then
         echo "include /etc/tgt/stack.d/*" | sudo tee -a /etc/tgt/targets.conf
     fi
 }
@@ -550,9 +550,7 @@
         local be be_name
         for be in ${CINDER_ENABLED_BACKENDS//,/ }; do
             be_name=${be##*:}
-            # FIXME(jamielennox): Remove --os-volume-api-version pinning when
-            # osc supports volume type create on v2 api. bug #1475060
-            openstack volume type create --os-volume-api-version 1 --property volume_backend_name="${be_name}" ${be_name}
+            openstack volume type create --property volume_backend_name="${be_name}" ${be_name}
         done
     fi
 }
@@ -567,7 +565,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_CINDER
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/cinder_backends/ceph b/lib/cinder_backends/ceph
index 7e9d2d3..9bff5be 100644
--- a/lib/cinder_backends/ceph
+++ b/lib/cinder_backends/ceph
@@ -22,7 +22,7 @@
 
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_CEPH=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -62,7 +62,7 @@
                 sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_BAK_CEPH_POOL} crush_ruleset ${RULE_ID}
             fi
         fi
-        sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_BAK_CEPH_USER} mon "allow r" osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_BAK_CEPH_POOL}" | sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_BAK_CEPH_USER}.keyring
+        sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_BAK_CEPH_USER} mon "allow r" osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_BAK_CEPH_POOL}, allow rwx pool=${CINDER_CEPH_POOL}" | sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_BAK_CEPH_USER}.keyring
         sudo chown $(whoami):$(whoami) ${CEPH_CONF_DIR}/ceph.client.${CINDER_BAK_CEPH_USER}.keyring
 
         iniset $CINDER_CONF DEFAULT backup_driver "cinder.backup.drivers.ceph"
@@ -76,7 +76,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_CEPH
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/glusterfs b/lib/cinder_backends/glusterfs
index 00c62e0..4e34f8e 100644
--- a/lib/cinder_backends/glusterfs
+++ b/lib/cinder_backends/glusterfs
@@ -19,7 +19,7 @@
 # configure_cinder_backend_glusterfs - Configure Cinder for GlusterFS backends
 
 # Save trace setting
-GLUSTERFS_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_GLUSTERFS=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -41,7 +41,7 @@
 
 
 # Restore xtrace
-$GLUSTERFS_XTRACE
+$_XTRACE_CINDER_GLUSTERFS
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/lvm b/lib/cinder_backends/lvm
index 411b82c..d927f9c 100644
--- a/lib/cinder_backends/lvm
+++ b/lib/cinder_backends/lvm
@@ -22,7 +22,7 @@
 
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_LVM=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -68,7 +68,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_LVM
 
 # mode: shell-script
 # End:
diff --git a/lib/cinder_backends/netapp_iscsi b/lib/cinder_backends/netapp_iscsi
index be9442e..5cce30a 100644
--- a/lib/cinder_backends/netapp_iscsi
+++ b/lib/cinder_backends/netapp_iscsi
@@ -20,7 +20,7 @@
 # configure_cinder_backend_netapp_iscsi - configure iSCSI
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_NETAPP=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -59,7 +59,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_NETAPP
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/netapp_nfs b/lib/cinder_backends/netapp_nfs
index dc919ad..7ba36d2 100644
--- a/lib/cinder_backends/netapp_nfs
+++ b/lib/cinder_backends/netapp_nfs
@@ -20,7 +20,7 @@
 # configure_cinder_backend_netapp_nfs - configure NFS
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_NETAPP=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -70,7 +70,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_NETAPP
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/nfs b/lib/cinder_backends/nfs
index fc51b2b..89a37a1 100644
--- a/lib/cinder_backends/nfs
+++ b/lib/cinder_backends/nfs
@@ -19,7 +19,7 @@
 # configure_cinder_backend_nfs - Configure Cinder for NFS backends
 
 # Save trace setting
-NFS_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_NFS=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -38,7 +38,7 @@
 
 
 # Restore xtrace
-$NFS_XTRACE
+$_XTRACE_CINDER_NFS
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/solidfire b/lib/cinder_backends/solidfire
index 7cc70fc..16bc527 100644
--- a/lib/cinder_backends/solidfire
+++ b/lib/cinder_backends/solidfire
@@ -17,7 +17,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_SOLIDFIRE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -42,7 +42,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_SOLIDFIRE
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/vmdk b/lib/cinder_backends/vmdk
index d5b9453..3a6a5cf 100644
--- a/lib/cinder_backends/vmdk
+++ b/lib/cinder_backends/vmdk
@@ -15,7 +15,7 @@
 # configure_cinder_backend_vmdk - Configure Cinder for VMware vmdk backends
 
 # Save trace setting
-VMDK_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_VMDK=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -40,7 +40,7 @@
 
 
 # Restore xtrace
-$VMDK_XTRACE
+$_XTRACE_CINDER_VMDK
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_backends/xiv b/lib/cinder_backends/xiv
index 6eadaae..e8b5da0 100644
--- a/lib/cinder_backends/xiv
+++ b/lib/cinder_backends/xiv
@@ -42,7 +42,7 @@
 # configure_cinder_backend_xiv - Configure Cinder for xiv backends
 
 # Save trace setting
-XIV_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_XIV=$(set +o | grep xtrace)
 set +o xtrace
 
 # Defaults
@@ -79,7 +79,7 @@
 }
 
 # Restore xtrace
-$XIV_XTRACE
+$_XTRACE_CINDER_XIV
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_plugins/XenAPINFS b/lib/cinder_plugins/XenAPINFS
index f730695..92135e7 100644
--- a/lib/cinder_plugins/XenAPINFS
+++ b/lib/cinder_plugins/XenAPINFS
@@ -15,7 +15,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_XENAPINFS=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -39,7 +39,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_XENAPINFS
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_plugins/glusterfs b/lib/cinder_plugins/glusterfs
index 35ceb27..329dd6c 100644
--- a/lib/cinder_plugins/glusterfs
+++ b/lib/cinder_plugins/glusterfs
@@ -15,7 +15,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_GLUSTERFS=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -45,7 +45,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_GLUSTERFS
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_plugins/nfs b/lib/cinder_plugins/nfs
index 83b3993..6e4ffe0 100644
--- a/lib/cinder_plugins/nfs
+++ b/lib/cinder_plugins/nfs
@@ -15,7 +15,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_NFS=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -36,7 +36,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_NFS
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_plugins/sheepdog b/lib/cinder_plugins/sheepdog
index ca343f7..558de46 100644
--- a/lib/cinder_plugins/sheepdog
+++ b/lib/cinder_plugins/sheepdog
@@ -15,7 +15,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_SHEEPDOG=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -34,7 +34,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_SHEEPDOG
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/cinder_plugins/vsphere b/lib/cinder_plugins/vsphere
index f14ddf0..1b28ffe 100644
--- a/lib/cinder_plugins/vsphere
+++ b/lib/cinder_plugins/vsphere
@@ -15,7 +15,7 @@
 # configure_cinder_driver - make configuration changes, including those to other services
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_CINDER_VSPHERE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -37,7 +37,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_CINDER_VSPHERE
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/database b/lib/database
index 13740b9..0d72052 100644
--- a/lib/database
+++ b/lib/database
@@ -20,7 +20,7 @@
 # and call register_database $DATABASE_TYPE
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_DB=$(set +o | grep xtrace)
 set +o xtrace
 
 DATABASE_BACKENDS=""
@@ -137,7 +137,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_DB
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/databases/mysql b/lib/databases/mysql
index cc74b33..f6cc922 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -8,7 +8,7 @@
 # - DATABASE_{HOST,USER,PASSWORD} must be defined
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_DB_MYSQL=$(set +o | grep xtrace)
 set +o xtrace
 
 MYSQL_DRIVER=${MYSQL_DRIVER:-PyMySQL}
@@ -154,6 +154,7 @@
         fi
     elif is_fedora; then
         install_package mariadb-server
+        sudo systemctl enable mariadb
     elif is_ubuntu; then
         install_package mysql-server
     else
@@ -178,7 +179,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_DB_MYSQL
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/databases/postgresql b/lib/databases/postgresql
index 78c7bed..204c257 100644
--- a/lib/databases/postgresql
+++ b/lib/databases/postgresql
@@ -8,7 +8,7 @@
 # - DATABASE_{HOST,USER,PASSWORD} must be defined
 
 # Save trace setting
-PG_XTRACE=$(set +o | grep xtrace)
+_XTRACE_PG=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -101,6 +101,9 @@
         install_package postgresql
     elif is_fedora || is_suse; then
         install_package postgresql-server
+        if is_fedora; then
+            sudo systemctl enable postgresql-server
+        fi
     else
         exit_distro_not_supported "postgresql installation"
     fi
@@ -119,7 +122,7 @@
 
 
 # Restore xtrace
-$PG_XTRACE
+$_XTRACE_PG
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/dlm b/lib/dlm
index 95e9b0a..74eb67e 100644
--- a/lib/dlm
+++ b/lib/dlm
@@ -19,7 +19,7 @@
 # - cleanup_dlm
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_DLM=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -100,7 +100,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_DLM
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/dstat b/lib/dstat
index fe4790b..b705948 100644
--- a/lib/dstat
+++ b/lib/dstat
@@ -13,7 +13,7 @@
 # - stop_dstat
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_DSTAT=$(set +o | grep xtrace)
 set +o xtrace
 
 # start_dstat() - Start running processes, including screen
@@ -34,4 +34,4 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_DSTAT
diff --git a/lib/glance b/lib/glance
index 2eb93a4..19e7937 100644
--- a/lib/glance
+++ b/lib/glance
@@ -21,7 +21,7 @@
 # - cleanup_glance
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_GLANCE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -115,6 +115,7 @@
     configure_auth_token_middleware $GLANCE_REGISTRY_CONF glance $GLANCE_AUTH_CACHE_DIR/registry
     iniset $GLANCE_REGISTRY_CONF DEFAULT notification_driver messaging
     iniset_rpc_backend glance $GLANCE_REGISTRY_CONF
+    iniset $GLANCE_REGISTRY_CONF DEFAULT graceful_shutdown_timeout "$SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT"
 
     cp $GLANCE_DIR/etc/glance-api.conf $GLANCE_API_CONF
     iniset $GLANCE_API_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -149,6 +150,7 @@
         iniset $GLANCE_API_CONF glance_store swift_store_config_file $GLANCE_SWIFT_STORE_CONF
         iniset $GLANCE_API_CONF glance_store default_swift_reference ref1
         iniset $GLANCE_API_CONF glance_store stores "file, http, swift"
+        iniset $GLANCE_API_CONF DEFAULT graceful_shutdown_timeout "$SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT"
 
         iniset $GLANCE_SWIFT_STORE_CONF ref1 user $SERVICE_TENANT_NAME:glance-swift
         iniset $GLANCE_SWIFT_STORE_CONF ref1 key $SERVICE_PASSWORD
@@ -167,6 +169,9 @@
         iniset $GLANCE_API_CONF DEFAULT bind_port $GLANCE_SERVICE_PORT_INT
         iniset $GLANCE_API_CONF DEFAULT public_endpoint $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT
         iniset $GLANCE_REGISTRY_CONF DEFAULT bind_port $GLANCE_REGISTRY_PORT_INT
+
+        iniset $GLANCE_API_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
+        iniset $GLANCE_REGISTRY_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
     fi
 
     # Register SSL certificates if provided
@@ -403,7 +408,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_GLANCE
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/heat b/lib/heat
index e42bdf0..df44b76 100644
--- a/lib/heat
+++ b/lib/heat
@@ -23,7 +23,7 @@
 # - cleanup_heat
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_HEAT=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -56,6 +56,10 @@
 HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates
 HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP}
 HEAT_API_PORT=${HEAT_API_PORT:-8004}
+HEAT_SERVICE_USER=${HEAT_SERVICE_USER:-heat}
+HEAT_TRUSTEE_USER=${HEAT_TRUSTEE_USER:-$HEAT_SERVICE_USER}
+HEAT_TRUSTEE_PASSWORD=${HEAT_TRUSTEE_PASSWORD:-$SERVICE_PASSWORD}
+HEAT_TRUSTEE_DOMAIN=${HEAT_TRUSTEE_DOMAIN:-default}
 
 # Support entry points installation of console scripts
 HEAT_BIN_DIR=$(get_python_exec_prefix)
@@ -65,9 +69,15 @@
     # for standalone, use defaults which require no service user
     HEAT_STACK_DOMAIN=$(trueorfalse False HEAT_STACK_DOMAIN)
     HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-password}
+    if [[ ${HEAT_DEFERRED_AUTH} != "password" ]]; then
+        # Heat does not support keystone trusts when deployed in
+        # standalone mode
+        die $LINENO \
+            'HEAT_DEFERRED_AUTH can only be set to "password" when HEAT_STANDALONE is True.'
+    fi
 else
     HEAT_STACK_DOMAIN=$(trueorfalse True HEAT_STACK_DOMAIN)
-    HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-trusts}
+    HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-}
 fi
 HEAT_PLUGIN_DIR=${HEAT_PLUGIN_DIR:-$DATA_DIR/heat/plugins}
 ENABLE_HEAT_PLUGINS=${ENABLE_HEAT_PLUGINS:-}
@@ -128,30 +138,34 @@
         setup_colorized_logging $HEAT_CONF DEFAULT tenant user
     fi
 
-    iniset $HEAT_CONF DEFAULT deferred_auth_method $HEAT_DEFERRED_AUTH
+    if [ ! -z "$HEAT_DEFERRED_AUTH" ]; then
+        iniset $HEAT_CONF DEFAULT deferred_auth_method $HEAT_DEFERRED_AUTH
+    fi
 
     if [ "$HEAT_USE_MOD_WSGI" == "True" ]; then
         _config_heat_apache_wsgi
     fi
 
-    # NOTE(jamielennox): heat re-uses specific values from the
-    # keystone_authtoken middleware group and so currently fails when using the
-    # auth plugin setup. This should be fixed in heat.  Heat is also the only
-    # service that requires the auth_uri to include a /v2.0. Remove this custom
-    # setup when bug #1300246 is resolved.
-    iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
     if [[ "$HEAT_STANDALONE" = "True" ]]; then
         iniset $HEAT_CONF paste_deploy flavor standalone
         iniset $HEAT_CONF clients_heat url "http://$HEAT_API_HOST:$HEAT_API_PORT/v1/%(tenant_id)s"
     else
-        iniset $HEAT_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
-        iniset $HEAT_CONF keystone_authtoken admin_user heat
-        iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
-        iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-        iniset $HEAT_CONF keystone_authtoken cafile $SSL_BUNDLE_FILE
-        iniset $HEAT_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR
+        configure_auth_token_middleware $HEAT_CONF heat $HEAT_AUTH_CACHE_DIR
     fi
 
+    # If HEAT_DEFERRED_AUTH is unset or explicitly set to trusts, configure
+    # the section for the client plugin associated with the trustee
+    if [ -z "$HEAT_DEFERRED_AUTH" -o "trusts" == "$HEAT_DEFERRED_AUTH" ]; then
+        iniset $HEAT_CONF trustee auth_plugin password
+        iniset $HEAT_CONF trustee auth_url $KEYSTONE_AUTH_URI
+        iniset $HEAT_CONF trustee username $HEAT_TRUSTEE_USER
+        iniset $HEAT_CONF trustee password $HEAT_TRUSTEE_PASSWORD
+        iniset $HEAT_CONF trustee user_domain_id $HEAT_TRUSTEE_DOMAIN
+    fi
+
+    # clients_keystone
+    iniset $HEAT_CONF clients_keystone auth_uri $KEYSTONE_AUTH_URI
+
     # ec2authtoken
     iniset $HEAT_CONF ec2authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
 
@@ -396,28 +410,13 @@
     fi
 
     if [[ "$HEAT_STACK_DOMAIN" == "True" ]]; then
-        # Note we have to pass token/endpoint here because the current endpoint and
-        # version negotiation in OSC means just --os-identity-api-version=3 won't work
-        D_ID=$(openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
-            --os-identity-api-version=3 domain list | grep ' heat ' | get_field 1)
-
-        if [[ -z "$D_ID" ]]; then
-            D_ID=$(openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
-                --os-identity-api-version=3 domain create heat \
-                --description "Owns users and projects created by heat" \
-                | grep ' id ' | get_field 2)
-            iniset $HEAT_CONF DEFAULT stack_user_domain_id ${D_ID}
-
-            openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
-                --os-identity-api-version=3 user create --password $SERVICE_PASSWORD \
-                --domain $D_ID heat_domain_admin \
-                --description "Manages users and projects created by heat"
-            openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
-                --os-identity-api-version=3 role add \
-                --user heat_domain_admin --domain ${D_ID} admin
-            iniset $HEAT_CONF DEFAULT stack_domain_admin heat_domain_admin
-            iniset $HEAT_CONF DEFAULT stack_domain_admin_password $SERVICE_PASSWORD
-        fi
+        # domain -> heat and user -> heat_domain_admin
+        domain_id=$(get_or_create_domain heat 'Owns users and projects created by heat')
+        iniset $HEAT_CONF DEFAULT stack_user_domain_id ${domain_id}
+        get_or_create_user heat_domain_admin $SERVICE_PASSWORD heat
+        get_or_add_user_domain_role admin heat_domain_admin heat
+        iniset $HEAT_CONF DEFAULT stack_domain_admin heat_domain_admin
+        iniset $HEAT_CONF DEFAULT stack_domain_admin_password $SERVICE_PASSWORD
     fi
 }
 
@@ -464,7 +463,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_HEAT
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/horizon b/lib/horizon
index ff63b06..dca3111 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -19,7 +19,7 @@
 # - cleanup_horizon
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_HORIZON=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -83,10 +83,7 @@
     # Message catalog compilation is handled by Django admin script,
     # so compiling them after the installation avoids Django installation twice.
     (cd $HORIZON_DIR; ./run_tests.sh -N --compilemessages)
-}
 
-# init_horizon() - Initialize databases, etc.
-function init_horizon {
     # ``local_settings.py`` is used to override horizon default settings.
     local local_settings=$HORIZON_DIR/openstack_dashboard/local/local_settings.py
     cp $HORIZON_SETTINGS $local_settings
@@ -113,6 +110,7 @@
     horizon_conf=$(apache_site_config_for horizon)
 
     # Configure apache to run horizon
+    # Set up the django horizon application to serve via apache/wsgi
     sudo sh -c "sed -e \"
         s,%USER%,$APACHE_USER,g;
         s,%GROUP%,$APACHE_GROUP,g;
@@ -133,7 +131,10 @@
         exit_distro_not_supported "horizon apache configuration"
     fi
     enable_apache_site horizon
+}
 
+# init_horizon() - Initialize databases, etc.
+function init_horizon {
     # Remove old log files that could mess with how DevStack detects whether Horizon
     # has been successfully started (see start_horizon() and functions::screen_it())
     # and run_process
@@ -147,6 +148,7 @@
         django_admin=django-admin.py
     fi
 
+    # These need to be run after horizon plugins are configured.
     DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin collectstatic --noinput
     DJANGO_SETTINGS_MODULE=openstack_dashboard.settings $django_admin compress --force
 
@@ -193,7 +195,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_HORIZON
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/infra b/lib/infra
index ab32efe..cf003cc 100644
--- a/lib/infra
+++ b/lib/infra
@@ -15,7 +15,7 @@
 # - install_infra
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_INFRA=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -50,7 +50,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_INFRA
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/ironic b/lib/ironic
deleted file mode 100644
index 6a32983..0000000
--- a/lib/ironic
+++ /dev/null
@@ -1,864 +0,0 @@
-#!/bin/bash
-#
-# lib/ironic
-# Functions to control the configuration and operation of the **Ironic** service
-
-# Dependencies:
-#
-# - ``functions`` file
-# - ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
-# - ``SERVICE_{TENANT_NAME|PASSWORD}`` must be defined
-# - ``SERVICE_HOST``
-# - ``KEYSTONE_TOKEN_FORMAT`` must be defined
-
-# ``stack.sh`` calls the entry points in this order:
-#
-# - install_ironic
-# - install_ironicclient
-# - init_ironic
-# - start_ironic
-# - stop_ironic
-# - cleanup_ironic
-
-# Save trace and pipefail settings
-XTRACE=$(set +o | grep xtrace)
-PIPEFAIL=$(set +o | grep pipefail)
-set +o xtrace
-set +o pipefail
-
-# Defaults
-# --------
-
-# Set up default directories
-GITDIR["python-ironicclient"]=$DEST/python-ironicclient
-GITDIR["ironic-lib"]=$DEST/ironic-lib
-
-IRONIC_DIR=$DEST/ironic
-IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent
-IRONIC_DATA_DIR=$DATA_DIR/ironic
-IRONIC_STATE_PATH=/var/lib/ironic
-IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
-IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
-IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
-IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
-IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
-
-# Deploy callback timeout can be changed from its default (1800), if required.
-IRONIC_CALLBACK_TIMEOUT=${IRONIC_CALLBACK_TIMEOUT:-}
-
-# Deploy to hardware platform
-IRONIC_HW_NODE_CPU=${IRONIC_HW_NODE_CPU:-1}
-IRONIC_HW_NODE_RAM=${IRONIC_HW_NODE_RAM:-512}
-IRONIC_HW_NODE_DISK=${IRONIC_HW_NODE_DISK:-10}
-IRONIC_HW_EPHEMERAL_DISK=${IRONIC_HW_EPHEMERAL_DISK:-0}
-# The file is composed of multiple lines, each line includes four field
-# separated by white space: IPMI address, MAC address, IPMI username
-# and IPMI password.
-#
-#   192.168.110.107 00:1e:67:57:50:4c root otc123
-IRONIC_IPMIINFO_FILE=${IRONIC_IPMIINFO_FILE:-$IRONIC_DATA_DIR/hardware_info}
-
-# Set up defaults for functional / integration testing
-IRONIC_NODE_UUID=${IRONIC_NODE_UUID:-`uuidgen`}
-IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$TOP_DIR/tools/ironic/scripts}
-IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_DIR/tools/ironic/templates}
-IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False IRONIC_BAREMETAL_BASIC_OPS)
-IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ssh,pxe_ipmitool}
-IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
-IRONIC_SSH_TIMEOUT=${IRONIC_SSH_TIMEOUT:-15}
-IRONIC_SSH_KEY_DIR=${IRONIC_SSH_KEY_DIR:-$IRONIC_DATA_DIR/ssh_keys}
-IRONIC_SSH_KEY_FILENAME=${IRONIC_SSH_KEY_FILENAME:-ironic_key}
-IRONIC_KEY_FILE=${IRONIC_KEY_FILE:-$IRONIC_SSH_KEY_DIR/$IRONIC_SSH_KEY_FILENAME}
-IRONIC_SSH_VIRT_TYPE=${IRONIC_SSH_VIRT_TYPE:-virsh}
-IRONIC_TFTPBOOT_DIR=${IRONIC_TFTPBOOT_DIR:-$IRONIC_DATA_DIR/tftpboot}
-IRONIC_TFTPSERVER_IP=${IRONIC_TFTPSERVER_IP:-$HOST_IP}
-IRONIC_VM_SSH_PORT=${IRONIC_VM_SSH_PORT:-22}
-IRONIC_VM_SSH_ADDRESS=${IRONIC_VM_SSH_ADDRESS:-$HOST_IP}
-IRONIC_VM_COUNT=${IRONIC_VM_COUNT:-1}
-IRONIC_VM_SPECS_CPU=${IRONIC_VM_SPECS_CPU:-1}
-IRONIC_VM_SPECS_RAM=${IRONIC_VM_SPECS_RAM:-512}
-IRONIC_VM_SPECS_DISK=${IRONIC_VM_SPECS_DISK:-10}
-IRONIC_VM_EPHEMERAL_DISK=${IRONIC_VM_EPHEMERAL_DISK:-0}
-IRONIC_VM_EMULATOR=${IRONIC_VM_EMULATOR:-/usr/bin/qemu-system-x86_64}
-IRONIC_VM_NETWORK_BRIDGE=${IRONIC_VM_NETWORK_BRIDGE:-brbm}
-IRONIC_VM_NETWORK_RANGE=${IRONIC_VM_NETWORK_RANGE:-192.0.2.0/24}
-IRONIC_VM_MACS_CSV_FILE=${IRONIC_VM_MACS_CSV_FILE:-$IRONIC_DATA_DIR/ironic_macs.csv}
-IRONIC_AUTHORIZED_KEYS_FILE=${IRONIC_AUTHORIZED_KEYS_FILE:-$HOME/.ssh/authorized_keys}
-
-# By default, baremetal VMs will console output to file.
-IRONIC_VM_LOG_CONSOLE=${IRONIC_VM_LOG_CONSOLE:-True}
-IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
-
-# Use DIB to create deploy ramdisk and kernel.
-IRONIC_BUILD_DEPLOY_RAMDISK=$(trueorfalse True IRONIC_BUILD_DEPLOY_RAMDISK)
-# If not use DIB, these files are used as deploy ramdisk/kernel.
-# (The value must be an absolute path)
-IRONIC_DEPLOY_RAMDISK=${IRONIC_DEPLOY_RAMDISK:-}
-IRONIC_DEPLOY_KERNEL=${IRONIC_DEPLOY_KERNEL:-}
-IRONIC_DEPLOY_ELEMENT=${IRONIC_DEPLOY_ELEMENT:-deploy-ironic}
-
-IRONIC_AGENT_KERNEL_URL=${IRONIC_AGENT_KERNEL_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe.vmlinuz}
-IRONIC_AGENT_RAMDISK_URL=${IRONIC_AGENT_RAMDISK_URL:-http://tarballs.openstack.org/ironic-python-agent/coreos/files/coreos_production_pxe_image-oem.cpio.gz}
-
-# Which deploy driver to use - valid choices right now
-# are ``pxe_ssh``, ``pxe_ipmitool``, ``agent_ssh`` and ``agent_ipmitool``.
-IRONIC_DEPLOY_DRIVER=${IRONIC_DEPLOY_DRIVER:-pxe_ssh}
-
-# TODO(agordeev): replace 'ubuntu' with host distro name getting
-IRONIC_DEPLOY_FLAVOR=${IRONIC_DEPLOY_FLAVOR:-ubuntu $IRONIC_DEPLOY_ELEMENT}
-
-# Support entry points installation of console scripts
-IRONIC_BIN_DIR=$(get_python_exec_prefix)
-
-# Ironic connection info.  Note the port must be specified.
-IRONIC_SERVICE_PROTOCOL=http
-IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
-IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
-
-# Enable iPXE
-IRONIC_IPXE_ENABLED=$(trueorfalse False IRONIC_IPXE_ENABLED)
-IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
-IRONIC_HTTP_SERVER=${IRONIC_HTTP_SERVER:-$HOST_IP}
-IRONIC_HTTP_PORT=${IRONIC_HTTP_PORT:-8088}
-
-# NOTE(lucasagomes): This flag is used to differentiate the nodes that
-# uses IPA as their deploy ramdisk from nodes that uses the agent_* drivers
-# (which also uses IPA but depends on Swift Temp URLs to work). At present,
-# all drivers that uses the iSCSI approach for their deployment supports
-# using both, IPA or bash ramdisks for the deployment. In the future we
-# want to remove the support for the bash ramdisk in favor of IPA, once
-# we get there this flag can be removed, and all conditionals that uses
-# it should just run by default.
-IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA=$(trueorfalse False IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA)
-
-# get_pxe_boot_file() - Get the PXE/iPXE boot file path
-function get_pxe_boot_file {
-    local relpath=syslinux/pxelinux.0
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        relpath=ipxe/undionly.kpxe
-    fi
-
-    local pxe_boot_file
-    if is_ubuntu; then
-        pxe_boot_file=/usr/lib/$relpath
-    elif is_fedora || is_suse; then
-        pxe_boot_file=/usr/share/$relpath
-    fi
-
-    echo $pxe_boot_file
-}
-
-# PXE boot image
-IRONIC_PXE_BOOT_IMAGE=${IRONIC_PXE_BOOT_IMAGE:-$(get_pxe_boot_file)}
-
-
-# Functions
-# ---------
-
-# Test if any Ironic services are enabled
-# is_ironic_enabled
-function is_ironic_enabled {
-    [[ ,${ENABLED_SERVICES} =~ ,"ir-" ]] && return 0
-    return 1
-}
-
-function is_ironic_hardware {
-    is_ironic_enabled && [[ -n "${IRONIC_DEPLOY_DRIVER##*_ssh}" ]] && return 0
-    return 1
-}
-
-function is_deployed_by_agent {
-    [[ -z "${IRONIC_DEPLOY_DRIVER%%agent*}" ]] && return 0
-    return 1
-}
-
-function is_deployed_with_ipa_ramdisk {
-    is_deployed_by_agent || [[ "$IRONIC_DEPLOY_DRIVER_ISCSI_WITH_IPA" == "True" ]] && return 0
-    return 1
-}
-
-# install_ironic() - Collect source and prepare
-function install_ironic {
-    # make sure all needed service were enabled
-    local req_services="key"
-    if [[ "$VIRT_DRIVER" == "ironic" ]]; then
-        req_services+=" nova glance neutron"
-    fi
-    for srv in $req_services; do
-        if ! is_service_enabled "$srv"; then
-            die $LINENO "$srv should be enabled for Ironic."
-        fi
-    done
-
-    if use_library_from_git "ironic-lib"; then
-        git_clone_by_name "ironic-lib"
-        setup_dev_lib "ironic-lib"
-    fi
-
-    git_clone $IRONIC_REPO $IRONIC_DIR $IRONIC_BRANCH
-    setup_develop $IRONIC_DIR
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        install_apache_wsgi
-    fi
-}
-
-# install_ironicclient() - Collect sources and prepare
-function install_ironicclient {
-    if use_library_from_git "python-ironicclient"; then
-        git_clone_by_name "python-ironicclient"
-        setup_dev_lib "python-ironicclient"
-        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ironicclient"]}/tools/,/etc/bash_completion.d/}ironic.bash_completion
-    else
-        # nothing actually "requires" ironicclient, so force instally from pypi
-        pip_install_gr python-ironicclient
-    fi
-}
-
-# _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
-function _cleanup_ironic_apache_wsgi {
-    sudo rm -rf $IRONIC_HTTP_DIR
-    disable_apache_site ironic
-    sudo rm -f $(apache_site_config_for ironic)
-    restart_apache_server
-}
-
-# _config_ironic_apache_wsgi() - Set WSGI config files of Ironic
-function _config_ironic_apache_wsgi {
-    local ironic_apache_conf
-    ironic_apache_conf=$(apache_site_config_for ironic)
-    sudo cp $FILES/apache-ironic.template $ironic_apache_conf
-    sudo sed -e "
-        s|%PUBLICPORT%|$IRONIC_HTTP_PORT|g;
-        s|%HTTPROOT%|$IRONIC_HTTP_DIR|g;
-    " -i $ironic_apache_conf
-    enable_apache_site ironic
-}
-
-# cleanup_ironic() - Remove residual data files, anything left over from previous
-# runs that would need to clean up.
-function cleanup_ironic {
-    sudo rm -rf $IRONIC_AUTH_CACHE_DIR $IRONIC_CONF_DIR
-}
-
-# configure_ironic_dirs() - Create all directories required by Ironic and
-# associated services.
-function configure_ironic_dirs {
-    sudo install -d -o $STACK_USER $IRONIC_CONF_DIR $STACK_USER $IRONIC_DATA_DIR \
-        $IRONIC_STATE_PATH $IRONIC_TFTPBOOT_DIR $IRONIC_TFTPBOOT_DIR/pxelinux.cfg
-    sudo chown -R $STACK_USER:$LIBVIRT_GROUP $IRONIC_TFTPBOOT_DIR
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        sudo install -d -o $STACK_USER -g $LIBVIRT_GROUP $IRONIC_HTTP_DIR
-    fi
-
-    if [ ! -f $IRONIC_PXE_BOOT_IMAGE ]; then
-        die $LINENO "PXE boot file $IRONIC_PXE_BOOT_IMAGE not found."
-    fi
-
-    # Copy PXE binary
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        cp $IRONIC_PXE_BOOT_IMAGE $IRONIC_TFTPBOOT_DIR
-    else
-        # Syslinux >= 5.00 pxelinux.0 binary is not "stand-alone" anymore,
-        # it depends on some c32 modules to work correctly.
-        # More info: http://www.syslinux.org/wiki/index.php/Library_modules
-        cp -aR $(dirname $IRONIC_PXE_BOOT_IMAGE)/*.{c32,0} $IRONIC_TFTPBOOT_DIR
-    fi
-}
-
-# configure_ironic() - Set config files, create data dirs, etc
-function configure_ironic {
-    configure_ironic_dirs
-
-    # Copy over ironic configuration file and configure common parameters.
-    cp $IRONIC_DIR/etc/ironic/ironic.conf.sample $IRONIC_CONF_FILE
-    iniset $IRONIC_CONF_FILE DEFAULT debug True
-    inicomment $IRONIC_CONF_FILE DEFAULT log_file
-    iniset $IRONIC_CONF_FILE database connection `database_connection_url ironic`
-    iniset $IRONIC_CONF_FILE DEFAULT state_path $IRONIC_STATE_PATH
-    iniset $IRONIC_CONF_FILE DEFAULT use_syslog $SYSLOG
-    # Configure Ironic conductor, if it was enabled.
-    if is_service_enabled ir-cond; then
-        configure_ironic_conductor
-    fi
-
-    # Configure Ironic API, if it was enabled.
-    if is_service_enabled ir-api; then
-        configure_ironic_api
-    fi
-
-    # Format logging
-    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
-        setup_colorized_logging $IRONIC_CONF_FILE DEFAULT tenant user
-    fi
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]]; then
-        _config_ironic_apache_wsgi
-    fi
-}
-
-# configure_ironic_api() - Is used by configure_ironic(). Performs
-# API specific configuration.
-function configure_ironic_api {
-    iniset $IRONIC_CONF_FILE DEFAULT auth_strategy keystone
-    iniset $IRONIC_CONF_FILE oslo_policy policy_file $IRONIC_POLICY_JSON
-
-    # TODO(Yuki Nishiwaki): This is a temporary work-around until Ironic is fixed(bug#1422632).
-    # These codes need to be changed to use the function of configure_auth_token_middleware
-    # after Ironic conforms to the new auth plugin.
-    iniset $IRONIC_CONF_FILE keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
-    iniset $IRONIC_CONF_FILE keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_user ironic
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_password $SERVICE_PASSWORD
-    iniset $IRONIC_CONF_FILE keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $IRONIC_CONF_FILE keystone_authtoken cafile $SSL_BUNDLE_FILE
-    iniset $IRONIC_CONF_FILE keystone_authtoken signing_dir $IRONIC_AUTH_CACHE_DIR/api
-
-    iniset_rpc_backend ironic $IRONIC_CONF_FILE
-    iniset $IRONIC_CONF_FILE api port $IRONIC_SERVICE_PORT
-
-    cp -p $IRONIC_DIR/etc/ironic/policy.json $IRONIC_POLICY_JSON
-}
-
-# configure_ironic_conductor() - Is used by configure_ironic().
-# Sets conductor specific settings.
-function configure_ironic_conductor {
-    cp $IRONIC_DIR/etc/ironic/rootwrap.conf $IRONIC_ROOTWRAP_CONF
-    cp -r $IRONIC_DIR/etc/ironic/rootwrap.d $IRONIC_CONF_DIR
-    local ironic_rootwrap
-    ironic_rootwrap=$(get_rootwrap_location ironic)
-    local rootwrap_isudoer_cmd="$ironic_rootwrap $IRONIC_CONF_DIR/rootwrap.conf *"
-
-    # Set up the rootwrap sudoers for ironic
-    local tempfile
-    tempfile=`mktemp`
-    echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_isudoer_cmd" >$tempfile
-    chmod 0440 $tempfile
-    sudo chown root:root $tempfile
-    sudo mv $tempfile /etc/sudoers.d/ironic-rootwrap
-
-    iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
-    iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
-    iniset $IRONIC_CONF_FILE conductor api_url $IRONIC_SERVICE_PROTOCOL://$HOST_IP:$IRONIC_SERVICE_PORT
-    if [[ -n "$IRONIC_CALLBACK_TIMEOUT" ]]; then
-        iniset $IRONIC_CONF_FILE conductor deploy_callback_timeout $IRONIC_CALLBACK_TIMEOUT
-    fi
-    iniset $IRONIC_CONF_FILE pxe tftp_server $IRONIC_TFTPSERVER_IP
-    iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
-    iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
-
-    local pxe_params=""
-    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
-        pxe_params+="nofb nomodeset vga=normal console=ttyS0"
-        if is_deployed_with_ipa_ramdisk; then
-            pxe_params+=" systemd.journald.forward_to_console=yes"
-        fi
-    fi
-    # When booting with less than 1GB, we need to switch from default tmpfs
-    # to ramfs for ramdisks to decompress successfully.
-    if (is_ironic_hardware && [[ "$IRONIC_HW_NODE_RAM" -lt 1024 ]]) ||
-        (! is_ironic_hardware && [[ "$IRONIC_VM_SPECS_RAM" -lt 1024 ]]); then
-        pxe_params+=" rootfstype=ramfs"
-    fi
-    if [[ -n "$pxe_params" ]]; then
-        iniset $IRONIC_CONF_FILE pxe pxe_append_params "$pxe_params"
-    fi
-
-    if is_deployed_by_agent; then
-        if [[ "$SWIFT_ENABLE_TEMPURLS" == "True" ]] ; then
-            iniset $IRONIC_CONF_FILE glance swift_temp_url_key $SWIFT_TEMPURL_KEY
-        else
-            die $LINENO "SWIFT_ENABLE_TEMPURLS must be True to use agent_ssh driver in Ironic."
-        fi
-        iniset $IRONIC_CONF_FILE glance swift_endpoint_url http://${HOST_IP}:${SWIFT_DEFAULT_BIND_PORT:-8080}
-        iniset $IRONIC_CONF_FILE glance swift_api_version v1
-        local tenant_id
-        tenant_id=$(get_or_create_project $SERVICE_TENANT_NAME default)
-        iniset $IRONIC_CONF_FILE glance swift_account AUTH_${tenant_id}
-        iniset $IRONIC_CONF_FILE glance swift_container glance
-        iniset $IRONIC_CONF_FILE glance swift_temp_url_duration 3600
-        iniset $IRONIC_CONF_FILE agent heartbeat_timeout 30
-        iniset $IRONIC_CONF_FILE agent agent_erase_devices_priority 0
-    fi
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        local pxebin
-        pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
-        iniset $IRONIC_CONF_FILE pxe ipxe_enabled True
-        iniset $IRONIC_CONF_FILE pxe pxe_config_template '\$pybasedir/drivers/modules/ipxe_config.template'
-        iniset $IRONIC_CONF_FILE pxe pxe_bootfile_name $pxebin
-        iniset $IRONIC_CONF_FILE pxe http_root $IRONIC_HTTP_DIR
-        iniset $IRONIC_CONF_FILE pxe http_url "http://$IRONIC_HTTP_SERVER:$IRONIC_HTTP_PORT"
-    fi
-}
-
-# create_ironic_cache_dir() - Part of the init_ironic() process
-function create_ironic_cache_dir {
-    # Create cache dir
-    sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/api
-    sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/api
-    rm -f $IRONIC_AUTH_CACHE_DIR/api/*
-    sudo mkdir -p $IRONIC_AUTH_CACHE_DIR/registry
-    sudo chown $STACK_USER $IRONIC_AUTH_CACHE_DIR/registry
-    rm -f $IRONIC_AUTH_CACHE_DIR/registry/*
-}
-
-# create_ironic_accounts() - Set up common required ironic accounts
-
-# Tenant               User       Roles
-# ------------------------------------------------------------------
-# service              ironic     admin        # if enabled
-function create_ironic_accounts {
-
-    # Ironic
-    if [[ "$ENABLED_SERVICES" =~ "ir-api" ]]; then
-        # Get ironic user if exists
-
-        # NOTE(Shrews): This user MUST have admin level privileges!
-        create_service_user "ironic" "admin"
-
-        if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
-
-            get_or_create_service "ironic" "baremetal" "Ironic baremetal provisioning service"
-            get_or_create_endpoint "baremetal" \
-                "$REGION_NAME" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT" \
-                "$IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT"
-        fi
-    fi
-}
-
-
-# init_ironic() - Initialize databases, etc.
-function init_ironic {
-    # Save private network as cleaning network
-    local cleaning_network_uuid
-    cleaning_network_uuid=$(neutron net-list | grep private | get_field 1)
-    iniset $IRONIC_CONF_FILE neutron cleaning_network_uuid ${cleaning_network_uuid}
-
-    # (Re)create  ironic database
-    recreate_database ironic
-
-    # Migrate ironic database
-    $IRONIC_BIN_DIR/ironic-dbsync --config-file=$IRONIC_CONF_FILE
-
-    create_ironic_cache_dir
-}
-
-# _ironic_bm_vm_names() - Generates list of names for baremetal VMs.
-function _ironic_bm_vm_names {
-    local idx
-    local num_vms
-    num_vms=$(($IRONIC_VM_COUNT - 1))
-    for idx in $(seq 0 $num_vms); do
-        echo "baremetal${IRONIC_VM_NETWORK_BRIDGE}_${idx}"
-    done
-}
-
-# start_ironic() - Start running processes, including screen
-function start_ironic {
-    # Start Ironic API server, if enabled.
-    if is_service_enabled ir-api; then
-        start_ironic_api
-    fi
-
-    # Start Ironic conductor, if enabled.
-    if is_service_enabled ir-cond; then
-        start_ironic_conductor
-    fi
-
-    # Start Apache if iPXE is enabled
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        restart_apache_server
-    fi
-}
-
-# start_ironic_api() - Used by start_ironic().
-# Starts Ironic API server.
-function start_ironic_api {
-    run_process ir-api "$IRONIC_BIN_DIR/ironic-api --config-file=$IRONIC_CONF_FILE"
-    echo "Waiting for ir-api ($IRONIC_HOSTPORT) to start..."
-    if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $IRONIC_SERVICE_PROTOCOL://$IRONIC_HOSTPORT; do sleep 1; done"; then
-        die $LINENO "ir-api did not start"
-    fi
-}
-
-# start_ironic_conductor() - Used by start_ironic().
-# Starts Ironic conductor.
-function start_ironic_conductor {
-    run_process ir-cond "$IRONIC_BIN_DIR/ironic-conductor --config-file=$IRONIC_CONF_FILE"
-    # TODO(romcheg): Find a way to check whether the conductor has started.
-}
-
-# stop_ironic() - Stop running processes
-function stop_ironic {
-    stop_process ir-api
-    stop_process ir-cond
-
-    # Cleanup the WSGI files
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        _cleanup_ironic_apache_wsgi
-    fi
-}
-
-function create_ovs_taps {
-    local ironic_net_id
-    ironic_net_id=$(neutron net-list | grep private | get_field 1)
-
-    # Work around: No netns exists on host until a Neutron port is created.  We
-    # need to create one in Neutron to know what netns to tap into prior to the
-    # first node booting.
-    local port_id
-    port_id=$(neutron port-create private | grep " id " | get_field 2)
-
-    # intentional sleep to make sure the tag has been set to port
-    sleep 10
-
-    local tapdev
-    tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -d'@' -f1 | cut -b2-)
-    local tag_id
-    tag_id=$(sudo ovs-vsctl show |grep ${tapdev} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
-
-    # make sure veth pair is not existing, otherwise delete its links
-    sudo ip link show ovs-tap1 && sudo ip link delete ovs-tap1
-    sudo ip link show brbm-tap1 && sudo ip link delete brbm-tap1
-    # create veth pair for future interconnection between br-int and brbm
-    sudo ip link add brbm-tap1 type veth peer name ovs-tap1
-    sudo ip link set dev brbm-tap1 up
-    sudo ip link set dev ovs-tap1 up
-
-    sudo ovs-vsctl -- --if-exists del-port ovs-tap1 -- add-port br-int ovs-tap1 tag=$tag_id
-    sudo ovs-vsctl -- --if-exists del-port brbm-tap1 -- add-port $IRONIC_VM_NETWORK_BRIDGE brbm-tap1
-
-    # Remove the port needed only for workaround.
-    neutron port-delete $port_id
-
-    # Finally, share the fixed tenant network across all tenants.  This allows the host
-    # to serve TFTP to a single network namespace via the tap device created above.
-    neutron net-update $ironic_net_id --shared true
-}
-
-function create_bridge_and_vms {
-    # Call libvirt setup scripts in a new shell to ensure any new group membership
-    sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/setup-network"
-    if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] ; then
-        local log_arg="$IRONIC_VM_LOG_DIR"
-    else
-        local log_arg=""
-    fi
-    local vm_name
-    for vm_name in $(_ironic_bm_vm_names); do
-        sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/create-node $vm_name \
-            $IRONIC_VM_SPECS_CPU $IRONIC_VM_SPECS_RAM $IRONIC_VM_SPECS_DISK \
-            amd64 $IRONIC_VM_NETWORK_BRIDGE $IRONIC_VM_EMULATOR \
-            $log_arg" >> $IRONIC_VM_MACS_CSV_FILE
-    done
-    create_ovs_taps
-}
-
-function wait_for_nova_resources {
-    # After nodes have been enrolled, we need to wait for both ironic and
-    # nova's periodic tasks to populate the resource tracker with available
-    # nodes and resources. Wait up to 2 minutes for a given resource before
-    # timing out.
-    local resource=$1
-    local expected_count=$2
-    local i
-    echo_summary "Waiting 2 minutes for Nova resource tracker to pick up $resource >= $expected_count"
-    for i in $(seq 1 120); do
-        if [ $(nova hypervisor-stats | grep " $resource " | get_field 2) -ge $expected_count ]; then
-            return 0
-        fi
-        sleep 1
-    done
-    die $LINENO "Timed out waiting for Nova hypervisor-stats $resource >= $expected_count"
-}
-
-function enroll_nodes {
-    local chassis_id
-    chassis_id=$(ironic chassis-create -d "ironic test chassis" | grep " uuid " | get_field 2)
-
-    if ! is_ironic_hardware; then
-        local ironic_node_cpu=$IRONIC_VM_SPECS_CPU
-        local ironic_node_ram=$IRONIC_VM_SPECS_RAM
-        local ironic_node_disk=$IRONIC_VM_SPECS_DISK
-        local ironic_ephemeral_disk=$IRONIC_VM_EPHEMERAL_DISK
-        local ironic_hwinfo_file=$IRONIC_VM_MACS_CSV_FILE
-        local node_options="\
-            -i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID \
-            -i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID \
-            -i ssh_virt_type=$IRONIC_SSH_VIRT_TYPE \
-            -i ssh_address=$IRONIC_VM_SSH_ADDRESS \
-            -i ssh_port=$IRONIC_VM_SSH_PORT \
-            -i ssh_username=$IRONIC_SSH_USERNAME \
-            -i ssh_key_filename=$IRONIC_KEY_FILE"
-    else
-        local ironic_node_cpu=$IRONIC_HW_NODE_CPU
-        local ironic_node_ram=$IRONIC_HW_NODE_RAM
-        local ironic_node_disk=$IRONIC_HW_NODE_DISK
-        local ironic_ephemeral_disk=$IRONIC_HW_EPHEMERAL_DISK
-        if [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
-            local ironic_hwinfo_file=$IRONIC_IPMIINFO_FILE
-        fi
-    fi
-
-    local total_nodes=0
-    local total_cpus=0
-    while read hardware_info; do
-        if ! is_ironic_hardware; then
-            local mac_address=$hardware_info
-        elif [[ -z "${IRONIC_DEPLOY_DRIVER##*_ipmitool}" ]]; then
-            local ipmi_address
-            ipmi_address=$(echo $hardware_info |awk  '{print $1}')
-            local mac_address
-            mac_address=$(echo $hardware_info |awk '{print $2}')
-            local ironic_ipmi_username
-            ironic_ipmi_username=$(echo $hardware_info |awk '{print $3}')
-            local ironic_ipmi_passwd
-            ironic_ipmi_passwd=$(echo $hardware_info |awk '{print $4}')
-            # Currently we require all hardware platform have same CPU/RAM/DISK info
-            # in future, this can be enhanced to support different type, and then
-            # we create the bare metal flavor with minimum value
-            local node_options="-i ipmi_address=$ipmi_address -i ipmi_password=$ironic_ipmi_passwd\
-                -i ipmi_username=$ironic_ipmi_username"
-            node_options+=" -i deploy_kernel=$IRONIC_DEPLOY_KERNEL_ID"
-            node_options+=" -i deploy_ramdisk=$IRONIC_DEPLOY_RAMDISK_ID"
-        fi
-
-        # First node created will be used for testing in ironic w/o glance
-        # scenario, so we need to know its UUID.
-        local standalone_node_uuid=""
-        if [ $total_nodes -eq 0 ]; then
-            standalone_node_uuid="--uuid $IRONIC_NODE_UUID"
-        fi
-
-        local node_id
-        node_id=$(ironic node-create $standalone_node_uuid\
-            --chassis_uuid $chassis_id \
-            --driver $IRONIC_DEPLOY_DRIVER \
-            --name node-$total_nodes \
-            -p cpus=$ironic_node_cpu\
-            -p memory_mb=$ironic_node_ram\
-            -p local_gb=$ironic_node_disk\
-            -p cpu_arch=x86_64 \
-            $node_options \
-            | grep " uuid " | get_field 2)
-
-        ironic port-create --address $mac_address --node $node_id
-
-        total_nodes=$((total_nodes+1))
-        total_cpus=$((total_cpus+$ironic_node_cpu))
-    done < $ironic_hwinfo_file
-
-    # create the nova flavor
-    # NOTE(adam_g): Attempting to use an autogenerated UUID for flavor id here uncovered
-    # bug (LP: #1333852) in Trove.  This can be changed to use an auto flavor id when the
-    # bug is fixed in Juno.
-    local adjusted_disk
-    adjusted_disk=$(($ironic_node_disk - $ironic_ephemeral_disk))
-    nova flavor-create --ephemeral $ironic_ephemeral_disk baremetal 551 $ironic_node_ram $adjusted_disk $ironic_node_cpu
-
-    nova flavor-key baremetal set "cpu_arch"="x86_64"
-
-    if [ "$VIRT_DRIVER" == "ironic" ]; then
-        wait_for_nova_resources "count" $total_nodes
-        wait_for_nova_resources "vcpus" $total_cpus
-    fi
-}
-
-function configure_iptables {
-    # enable tftp natting for allowing connections to HOST_IP's tftp server
-    sudo modprobe nf_conntrack_tftp
-    sudo modprobe nf_nat_tftp
-    # explicitly allow DHCP - packets are occasionally being dropped here
-    sudo iptables -I INPUT -p udp --dport 67:68 --sport 67:68 -j ACCEPT || true
-    # nodes boot from TFTP and callback to the API server listening on $HOST_IP
-    sudo iptables -I INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
-    sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
-    if is_deployed_by_agent; then
-        # agent ramdisk gets instance image from swift
-        sudo iptables -I INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
-    fi
-
-    if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
-        sudo iptables -I INPUT -d $HOST_IP -p tcp --dport $IRONIC_HTTP_PORT -j ACCEPT || true
-    fi
-}
-
-function configure_tftpd {
-    # stop tftpd and setup serving via xinetd
-    stop_service tftpd-hpa || true
-    [ -f /etc/init/tftpd-hpa.conf ] && echo "manual" | sudo tee /etc/init/tftpd-hpa.override
-    sudo cp $IRONIC_TEMPLATES_DIR/tftpd-xinetd.template /etc/xinetd.d/tftp
-    sudo sed -e "s|%TFTPBOOT_DIR%|$IRONIC_TFTPBOOT_DIR|g" -i /etc/xinetd.d/tftp
-
-    # setup tftp file mapping to satisfy requests at the root (booting) and
-    # /tftpboot/ sub-dir (as per deploy-ironic elements)
-    echo "r ^([^/]) $IRONIC_TFTPBOOT_DIR/\1" >$IRONIC_TFTPBOOT_DIR/map-file
-    echo "r ^(/tftpboot/) $IRONIC_TFTPBOOT_DIR/\2" >>$IRONIC_TFTPBOOT_DIR/map-file
-
-    chmod -R 0755 $IRONIC_TFTPBOOT_DIR
-    restart_service xinetd
-}
-
-function configure_ironic_ssh_keypair {
-    if [[ ! -d $HOME/.ssh ]]; then
-        mkdir -p $HOME/.ssh
-        chmod 700 $HOME/.ssh
-    fi
-    if [[ ! -e $IRONIC_KEY_FILE ]]; then
-        if [[ ! -d $(dirname $IRONIC_KEY_FILE) ]]; then
-            mkdir -p $(dirname $IRONIC_KEY_FILE)
-        fi
-        echo -e 'n\n' | ssh-keygen -q -t rsa -P '' -f $IRONIC_KEY_FILE
-    fi
-    cat $IRONIC_KEY_FILE.pub | tee -a $IRONIC_AUTHORIZED_KEYS_FILE
-}
-
-function ironic_ssh_check {
-    local key_file=$1
-    local floating_ip=$2
-    local port=$3
-    local default_instance_user=$4
-    local active_timeout=$5
-    if ! timeout $active_timeout sh -c "while ! ssh -p $port -o StrictHostKeyChecking=no -i $key_file ${default_instance_user}@$floating_ip echo success; do sleep 1; done"; then
-        die $LINENO "server didn't become ssh-able!"
-    fi
-}
-
-function configure_ironic_auxiliary {
-    configure_ironic_ssh_keypair
-    ironic_ssh_check $IRONIC_KEY_FILE $IRONIC_VM_SSH_ADDRESS $IRONIC_VM_SSH_PORT $IRONIC_SSH_USERNAME $IRONIC_SSH_TIMEOUT
-}
-
-function build_ipa_coreos_ramdisk {
-    echo "Building ironic-python-agent deploy ramdisk"
-    local kernel_path=$1
-    local ramdisk_path=$2
-    git_clone $IRONIC_PYTHON_AGENT_REPO $IRONIC_PYTHON_AGENT_DIR $IRONIC_PYTHON_AGENT_BRANCH
-    cd $IRONIC_PYTHON_AGENT_DIR
-    imagebuild/coreos/build_coreos_image.sh
-    cp imagebuild/coreos/UPLOAD/coreos_production_pxe_image-oem.cpio.gz $ramdisk_path
-    cp imagebuild/coreos/UPLOAD/coreos_production_pxe.vmlinuz $kernel_path
-    sudo rm -rf UPLOAD
-    cd -
-}
-
-# build deploy kernel+ramdisk, then upload them to glance
-# this function sets ``IRONIC_DEPLOY_KERNEL_ID``, ``IRONIC_DEPLOY_RAMDISK_ID``
-function upload_baremetal_ironic_deploy {
-    declare -g IRONIC_DEPLOY_KERNEL_ID IRONIC_DEPLOY_RAMDISK_ID
-    echo_summary "Creating and uploading baremetal images for ironic"
-
-    # install diskimage-builder
-    if [[ $(type -P ramdisk-image-create) == "" ]]; then
-        pip_install_gr "diskimage-builder"
-    fi
-
-    if [ -z "$IRONIC_DEPLOY_KERNEL" -o -z "$IRONIC_DEPLOY_RAMDISK" ]; then
-        local IRONIC_DEPLOY_KERNEL_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.kernel
-        local IRONIC_DEPLOY_RAMDISK_PATH=$TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER.initramfs
-    else
-        local IRONIC_DEPLOY_KERNEL_PATH=$IRONIC_DEPLOY_KERNEL
-        local IRONIC_DEPLOY_RAMDISK_PATH=$IRONIC_DEPLOY_RAMDISK
-    fi
-
-    if [ ! -e "$IRONIC_DEPLOY_RAMDISK_PATH" -o ! -e "$IRONIC_DEPLOY_KERNEL_PATH" ]; then
-        # files don't exist, need to build them
-        if [ "$IRONIC_BUILD_DEPLOY_RAMDISK" = "True" ]; then
-            # we can build them only if we're not offline
-            if [ "$OFFLINE" != "True" ]; then
-                if is_deployed_with_ipa_ramdisk; then
-                    build_ipa_coreos_ramdisk $IRONIC_DEPLOY_KERNEL_PATH $IRONIC_DEPLOY_RAMDISK_PATH
-                else
-                    ramdisk-image-create $IRONIC_DEPLOY_FLAVOR \
-                        -o $TOP_DIR/files/ir-deploy-$IRONIC_DEPLOY_DRIVER
-                fi
-            else
-                die $LINENO "Deploy kernel+ramdisk files don't exist and cannot be build in OFFLINE mode"
-            fi
-        else
-            if is_deployed_with_ipa_ramdisk; then
-                # download the agent image tarball
-                wget "$IRONIC_AGENT_KERNEL_URL" -O $IRONIC_DEPLOY_KERNEL_PATH
-                wget "$IRONIC_AGENT_RAMDISK_URL" -O $IRONIC_DEPLOY_RAMDISK_PATH
-            else
-                die $LINENO "Deploy kernel+ramdisk files don't exist and their building was disabled explicitly by IRONIC_BUILD_DEPLOY_RAMDISK"
-            fi
-        fi
-    fi
-
-    local token
-    token=$(openstack token issue -c id -f value)
-    die_if_not_set $LINENO token "Keystone fail to get token"
-
-    # load them into glance
-    IRONIC_DEPLOY_KERNEL_ID=$(openstack \
-        --os-token $token \
-        --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
-        image create \
-        $(basename $IRONIC_DEPLOY_KERNEL_PATH) \
-        --public --disk-format=aki \
-        --container-format=aki \
-        < $IRONIC_DEPLOY_KERNEL_PATH  | grep ' id ' | get_field 2)
-    IRONIC_DEPLOY_RAMDISK_ID=$(openstack \
-        --os-token $token \
-        --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
-        image create \
-        $(basename $IRONIC_DEPLOY_RAMDISK_PATH) \
-        --public --disk-format=ari \
-        --container-format=ari \
-        < $IRONIC_DEPLOY_RAMDISK_PATH  | grep ' id ' | get_field 2)
-}
-
-function prepare_baremetal_basic_ops {
-    if ! is_ironic_hardware; then
-        configure_ironic_auxiliary
-    fi
-    upload_baremetal_ironic_deploy
-    if ! is_ironic_hardware; then
-        create_bridge_and_vms
-    fi
-    enroll_nodes
-    configure_tftpd
-    configure_iptables
-}
-
-function cleanup_baremetal_basic_ops {
-    rm -f $IRONIC_VM_MACS_CSV_FILE
-    if [ -f $IRONIC_KEY_FILE ]; then
-        local key
-        key=$(cat $IRONIC_KEY_FILE.pub)
-        # remove public key from authorized_keys
-        grep -v "$key" $IRONIC_AUTHORIZED_KEYS_FILE > temp && mv temp $IRONIC_AUTHORIZED_KEYS_FILE
-        chmod 0600 $IRONIC_AUTHORIZED_KEYS_FILE
-    fi
-    sudo rm -rf $IRONIC_DATA_DIR $IRONIC_STATE_PATH
-
-    local vm_name
-    for vm_name in $(_ironic_bm_vm_names); do
-        sudo su $STACK_USER -c "$IRONIC_SCRIPTS_DIR/cleanup-node $vm_name $IRONIC_VM_NETWORK_BRIDGE"
-    done
-
-    sudo rm -rf /etc/xinetd.d/tftp /etc/init/tftpd-hpa.override
-    restart_service xinetd
-    sudo iptables -D INPUT -d $HOST_IP -p udp --dport 69 -j ACCEPT || true
-    sudo iptables -D INPUT -d $HOST_IP -p tcp --dport $IRONIC_SERVICE_PORT -j ACCEPT || true
-    if is_deployed_by_agent; then
-        # agent ramdisk gets instance image from swift
-        sudo iptables -D INPUT -d $HOST_IP -p tcp --dport ${SWIFT_DEFAULT_BIND_PORT:-8080} -j ACCEPT || true
-    fi
-    sudo rmmod nf_conntrack_tftp || true
-    sudo rmmod nf_nat_tftp || true
-}
-
-# Restore xtrace + pipefail
-$XTRACE
-$PIPEFAIL
-
-# Tell emacs to use shell-script-mode
-## Local variables:
-## mode: shell-script
-## End:
diff --git a/lib/keystone b/lib/keystone
index 5a2afbf..78904de 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -12,7 +12,6 @@
 # - ``IDENTITY_API_VERSION``
 # - ``BASE_SQL_CONN``
 # - ``SERVICE_HOST``, ``SERVICE_PROTOCOL``
-# - ``SERVICE_TOKEN``
 # - ``S3_SERVICE_PORT`` (template backend only)
 
 # ``stack.sh`` calls the entry points in this order:
@@ -22,13 +21,14 @@
 # - _config_keystone_apache_wsgi
 # - init_keystone
 # - start_keystone
+# - bootstrap_keystone
 # - create_keystone_accounts
 # - stop_keystone
 # - cleanup_keystone
 # - _cleanup_keystone_apache_wsgi
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_KEYSTONE=$(set +o | grep xtrace)
 set +o xtrace
 
 # Defaults
@@ -52,10 +52,6 @@
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
 KEYSTONE_PASTE_INI=${KEYSTONE_PASTE_INI:-$KEYSTONE_CONF_DIR/keystone-paste.ini}
 
-# Set up additional extensions, such as oauth1, federation
-# Example of KEYSTONE_EXTENSIONS=oauth1,federation
-KEYSTONE_EXTENSIONS=${KEYSTONE_EXTENSIONS:-}
-
 # Toggle for deploying Keystone under HTTPD + mod_wsgi
 KEYSTONE_USE_MOD_WSGI=${KEYSTONE_USE_MOD_WSGI:-${ENABLE_HTTPD_MOD_WSGI_SERVICES}}
 
@@ -72,6 +68,12 @@
 # Select the Assignment backend driver
 KEYSTONE_ASSIGNMENT_BACKEND=${KEYSTONE_ASSIGNMENT_BACKEND:-sql}
 
+# Select the Role backend driver
+KEYSTONE_ROLE_BACKEND=${KEYSTONE_ROLE_BACKEND:-sql}
+
+# Select the Resource backend driver
+KEYSTONE_RESOURCE_BACKEND=${KEYSTONE_RESOURCE_BACKEND:-sql}
+
 # Select Keystone's token provider (and format)
 # Choose from 'uuid', 'pki', 'pkiz', or 'fernet'
 KEYSTONE_TOKEN_FORMAT=${KEYSTONE_TOKEN_FORMAT:-}
@@ -192,8 +194,6 @@
         inidelete $KEYSTONE_PASTE_INI composite:admin \\/v2.0
     fi
 
-    configure_keystone_extensions
-
     # Rewrite stock ``keystone.conf``
 
     if is_service_enabled ldap; then
@@ -215,11 +215,11 @@
 
     iniset $KEYSTONE_CONF identity driver "$KEYSTONE_IDENTITY_BACKEND"
     iniset $KEYSTONE_CONF assignment driver "$KEYSTONE_ASSIGNMENT_BACKEND"
+    iniset $KEYSTONE_CONF role driver "$KEYSTONE_ROLE_BACKEND"
+    iniset $KEYSTONE_CONF resource driver "$KEYSTONE_RESOURCE_BACKEND"
 
     iniset_rpc_backend keystone $KEYSTONE_CONF
 
-    iniset $KEYSTONE_CONF eventlet_server admin_bind_host "$KEYSTONE_ADMIN_BIND_HOST"
-
     # Register SSL certificates if provided
     if is_ssl_enabled_service key; then
         ensure_certificates KEYSTONE
@@ -233,9 +233,10 @@
         # Set the service ports for a proxy to take the originals
         iniset $KEYSTONE_CONF eventlet_server public_port $KEYSTONE_SERVICE_PORT_INT
         iniset $KEYSTONE_CONF eventlet_server admin_port $KEYSTONE_AUTH_PORT_INT
-    fi
 
-    iniset $KEYSTONE_CONF DEFAULT admin_token "$SERVICE_TOKEN"
+        iniset $KEYSTONE_CONF DEFAULT public_endpoint $KEYSTONE_SERVICE_URI
+        iniset $KEYSTONE_CONF DEFAULT admin_endpoint $KEYSTONE_AUTH_URI
+    fi
 
     if [[ "$KEYSTONE_TOKEN_FORMAT" != "" ]]; then
         iniset $KEYSTONE_CONF token provider $KEYSTONE_TOKEN_FORMAT
@@ -296,35 +297,17 @@
         iniset $KEYSTONE_CONF DEFAULT logging_debug_format_suffix "%(funcName)s %(pathname)s:%(lineno)d"
         iniset $KEYSTONE_CONF DEFAULT logging_exception_prefix "%(process)d TRACE %(name)s %(instance)s"
         _config_keystone_apache_wsgi
+    else
+        iniset $KEYSTONE_CONF eventlet_server admin_bind_host "$KEYSTONE_ADMIN_BIND_HOST"
+        iniset $KEYSTONE_CONF eventlet_server admin_workers "$API_WORKERS"
+        # Public workers will use the server default, typically number of CPU.
     fi
 
     iniset $KEYSTONE_CONF DEFAULT max_token_size 16384
 
-    iniset $KEYSTONE_CONF eventlet_server admin_workers "$API_WORKERS"
-    # Public workers will use the server default, typically number of CPU.
-
     iniset $KEYSTONE_CONF fernet_tokens key_repository "$KEYSTONE_CONF_DIR/fernet-keys/"
 }
 
-function configure_keystone_extensions {
-    # Add keystone extension into keystone v3 application pipeline
-    local extension_value
-    local api_v3
-    local extension
-    local api_v3_extension
-    for extension_value in ${KEYSTONE_EXTENSIONS//,/ }; do
-        if [[ -z "${extension_value}" ]]; then
-            continue
-        fi
-        api_v3=$(iniget $KEYSTONE_PASTE_INI pipeline:api_v3 pipeline)
-        extension=$(echo $api_v3 | sed -ne "/${extension_value}/ p;" )
-        if [[ -z $extension ]]; then
-            api_v3_extension=$(echo $api_v3 | sed -ne "s/service_v3/${extension_value}_extension service_v3/p;" )
-            iniset $KEYSTONE_PASTE_INI pipeline:api_v3 pipeline "$api_v3_extension"
-        fi
-    done
-}
-
 # create_keystone_accounts() - Sets up common required keystone accounts
 
 # Tenant               User       Roles
@@ -347,14 +330,17 @@
 # Migrated from keystone_data.sh
 function create_keystone_accounts {
 
-    # admin
+    # The keystone bootstrapping process (performed via keystone-manage bootstrap)
+    # creates an admin user, admin role and admin project. As a sanity check
+    # we exercise the CLI to retrieve the IDs for these values.
     local admin_tenant
-    admin_tenant=$(get_or_create_project "admin" default)
+    admin_tenant=$(openstack project show "admin" -f value -c id)
     local admin_user
-    admin_user=$(get_or_create_user "admin" "$ADMIN_PASSWORD" default)
+    admin_user=$(openstack user show "admin" -f value -c id)
     local admin_role
-    admin_role=$(get_or_create_role "admin")
-    get_or_add_user_project_role $admin_role $admin_user $admin_tenant
+    admin_role=$(openstack role show "admin" -f value -c id)
+
+    get_or_add_user_domain_role $admin_role $admin_user default
 
     # Create service project/role
     get_or_create_project "$SERVICE_TENANT_NAME" default
@@ -403,17 +389,6 @@
     get_or_add_group_project_role $member_role $non_admin_group $demo_tenant
     get_or_add_group_project_role $another_role $non_admin_group $demo_tenant
     get_or_add_group_project_role $admin_role $admin_group $admin_tenant
-
-    # Keystone
-    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
-
-        get_or_create_service "keystone" "identity" "Keystone Identity Service"
-        get_or_create_endpoint "identity" \
-            "$REGION_NAME" \
-            "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION" \
-            "$KEYSTONE_AUTH_PROTOCOL://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT/v$IDENTITY_API_VERSION" \
-            "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION"
-    fi
 }
 
 # Create a user that is capable of verifying keystone tokens for use with auth_token middleware.
@@ -444,7 +419,7 @@
     local signing_dir=$3
     local section=${4:-keystone_authtoken}
 
-    iniset $conf_file $section auth_plugin password
+    iniset $conf_file $section auth_type password
     iniset $conf_file $section auth_url $KEYSTONE_AUTH_URI
     iniset $conf_file $section username $admin_user
     iniset $conf_file $section password $SERVICE_PASSWORD
@@ -469,14 +444,6 @@
     # Initialize keystone database
     $KEYSTONE_BIN_DIR/keystone-manage db_sync
 
-    local extension_value
-    for extension_value in ${KEYSTONE_EXTENSIONS//,/ }; do
-        if [[ -z "${extension_value}" ]]; then
-            continue
-        fi
-        $KEYSTONE_BIN_DIR/keystone-manage db_sync --extension "${extension_value}"
-    done
-
     if [[ "$KEYSTONE_TOKEN_FORMAT" == "pki" || "$KEYSTONE_TOKEN_FORMAT" == "pkiz" ]]; then
         # Set up certificates
         rm -rf $KEYSTONE_CONF_DIR/ssl
@@ -537,6 +504,11 @@
     fi
     git_clone $KEYSTONE_REPO $KEYSTONE_DIR $KEYSTONE_BRANCH
     setup_develop $KEYSTONE_DIR
+
+    if is_service_enabled ldap; then
+        setup_develop $KEYSTONE_DIR ldap
+    fi
+
     if [ "$KEYSTONE_USE_MOD_WSGI" == "True" ]; then
         install_apache_wsgi
         if is_ssl_enabled_service "key"; then
@@ -590,9 +562,58 @@
     stop_process key
 }
 
+# bootstrap_keystone() - Initialize user, role and project
+# This function uses the following GLOBAL variables:
+# - ``KEYSTONE_BIN_DIR``
+# - ``ADMIN_PASSWORD``
+# - ``IDENTITY_API_VERSION``
+# - ``KEYSTONE_CATALOG_BACKEND``
+# - ``KEYSTONE_AUTH_URI``
+# - ``REGION_NAME``
+# - ``KEYSTONE_SERVICE_PROTOCOL``
+# - ``KEYSTONE_SERVICE_HOST``
+# - ``KEYSTONE_SERVICE_PORT``
+function bootstrap_keystone {
+
+    # Initialize keystone, this will create an 'admin' user, 'admin' project,
+    # 'admin' role, and assign the user the role on the project. These resources
+    # are created only if they do not already exist.
+    $KEYSTONE_BIN_DIR/keystone-manage bootstrap --bootstrap-password $ADMIN_PASSWORD
+
+    # Create the keystone service and endpoints. To do this with the new
+    # bootstrapping process, we need to get a token and use that token to
+    # interact with the new APIs. The token will only be used to create services
+    # and endpoints, thus creating a minimal service catalog.
+    # They are unset immediately after.
+    # TODO(stevemar): OpenStackClient and KeystoneClient do not have support to
+    # handle interactions that not return service catalogs. Eventually remove
+    # this section when the support is in place. Use token based auth for now.
+    local token_id
+    token_id=$(openstack token issue -c id -f value \
+        --os-username admin --os-project-name admin \
+        --os-user-domain-id default --os-project-domain-id default \
+        --os-identity-api-version 3 --os-auth-url $KEYSTONE_AUTH_URI \
+        --os-password $ADMIN_PASSWORD)
+
+    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
+
+        export OS_TOKEN=$token_id
+        export OS_URL=$KEYSTONE_AUTH_URI/v3
+        export OS_IDENTITY_API_VERSION=3
+
+        get_or_create_service "keystone" "identity" "Keystone Identity Service"
+        get_or_create_endpoint "identity" \
+            "$REGION_NAME" \
+            "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION" \
+            "$KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION" \
+            "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$IDENTITY_API_VERSION"
+    fi
+
+    unset OS_TOKEN OS_URL OS_IDENTITY_API_VERSION
+}
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_KEYSTONE
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/ldap b/lib/ldap
index 0414fea..4cea812 100644
--- a/lib/ldap
+++ b/lib/ldap
@@ -8,7 +8,7 @@
 # - install_ldap()
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LDAP=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -145,8 +145,6 @@
         sudo ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
     fi
 
-    pip_install_gr ldappool
-
     rm -rf $tmp_ldap_dir
 }
 
@@ -166,7 +164,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LDAP
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/lvm b/lib/lvm
index 468a99a..ae6023a 100644
--- a/lib/lvm
+++ b/lib/lvm
@@ -16,7 +16,7 @@
 
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_LVM=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -182,7 +182,7 @@
 }
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_LVM
 
 # mode: shell-script
 # End:
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index 85f7fc0..692d5ea 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -112,6 +112,12 @@
 NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
 export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"}
 
+# Default provider for load balancer service
+DEFAULT_LB_PROVIDER=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
+
+# Default provider for VPN service
+DEFAULT_VPN_PROVIDER=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
+
 # Agent binaries.  Note, binary paths for other agents are set in per-service
 # scripts in lib/neutron_plugins/services/
 AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent"
@@ -165,6 +171,9 @@
 
 ## Provider Network Information
 PROVIDER_SUBNET_NAME=${PROVIDER_SUBNET_NAME:-"provider_net"}
+IPV6_PROVIDER_SUBNET_NAME=${IPV6_PROVIDER_SUBNET_NAME:-"provider_net_v6"}
+IPV6_PROVIDER_FIXED_RANGE=${IPV6_PROVIDER_FIXED_RANGE:-}
+IPV6_PROVIDER_NETWORK_GATEWAY=${IPV6_PROVIDER_NETWORK_GATEWAY:-}
 
 # Define the public bridge that will transmit traffic from VMs to the
 # physical network - used by both the OVS and Linux Bridge drivers.
@@ -357,7 +366,7 @@
 fi
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -545,14 +554,16 @@
             die_if_not_set $LINENO SUBNET_ID "Failure creating SUBNET_ID for $PROVIDER_SUBNET_NAME $TENANT_ID"
         fi
 
-        if [[ "$IP_VERSION" =~ .*6 ]]; then
-            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $V6_NETWORK_GATEWAY --name $PROVIDER_SUBNET_NAME_V6 --subnetpool_id None $NET_ID $FIXED_RANGE_V6 | grep 'id' | get_field 2)
-            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $PROVIDER_SUBNET_NAME_V6 $TENANT_ID"
+        if [[ "$IP_VERSION" =~ .*6 ]] && [[ -n "$IPV6_PROVIDER_FIXED_RANGE" ]] && [[ -n "$IPV6_PROVIDER_NETWORK_GATEWAY" ]]; then
+            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode $IPV6_ADDRESS_MODE --gateway $IPV6_PROVIDER_NETWORK_GATEWAY --name $IPV6_PROVIDER_SUBNET_NAME --subnetpool None $NET_ID $IPV6_PROVIDER_FIXED_RANGE | grep 'id' | get_field 2)
+            die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $IPV6_PROVIDER_SUBNET_NAME $TENANT_ID"
         fi
 
-        sudo ip link set $OVS_PHYSICAL_BRIDGE up
-        sudo ip link set br-int up
-        sudo ip link set $PUBLIC_INTERFACE up
+        if [[ $Q_AGENT == "openvswitch" ]]; then
+            sudo ip link set $OVS_PHYSICAL_BRIDGE up
+            sudo ip link set br-int up
+            sudo ip link set $PUBLIC_INTERFACE up
+        fi
     else
         NET_ID=$(neutron net-create --tenant-id $TENANT_ID "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2)
         die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PRIVATE_NETWORK_NAME $TENANT_ID"
@@ -698,7 +709,7 @@
 function start_neutron_l2_agent {
     run_process q-agt "$AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
 
-    if is_provider_network; then
+    if is_provider_network && [[ $Q_AGENT == "openvswitch" ]]; then
         sudo ovs-vsctl --no-wait -- --may-exist add-port $OVS_PHYSICAL_BRIDGE $PUBLIC_INTERFACE
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
@@ -772,6 +783,10 @@
     if is_service_enabled q-metering; then
         neutron_metering_stop
     fi
+
+    if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
+        sudo pkill -9 -f $NEUTRON_ROOTWRAP-daemon || :
+    fi
 }
 
 # stop_neutron() - Stop running processes (non-screen)
@@ -787,7 +802,8 @@
     local from_intf=$1
     local to_intf=$2
     local add_ovs_port=$3
-    local af=$4
+    local del_ovs_port=$4
+    local af=$5
 
     if [[ -n "$from_intf" && -n "$to_intf" ]]; then
         # Remove the primary IP address from $from_intf and add it to $to_intf,
@@ -797,17 +813,13 @@
 
         local IP_ADD=""
         local IP_DEL=""
+        local IP_UP=""
         local DEFAULT_ROUTE_GW
         DEFAULT_ROUTE_GW=$(ip -f $af r | awk "/default.+$from_intf/ { print \$3; exit }")
         local ADD_OVS_PORT=""
+        local DEL_OVS_PORT=""
 
-        if [[ $af == "inet" ]]; then
-            IP_BRD=$(ip -f $af a s dev $from_intf | grep inet | awk '{ print $2, $3, $4; exit }')
-        fi
-
-        if [[ $af == "inet6" ]]; then
-            IP_BRD=$(ip -f $af a s dev $from_intf | grep 'scope global' | sed '/temporary/d' | awk '{ print $2, $3, $4; exit }')
-        fi
+        IP_BRD=$(ip -f $af a s dev $from_intf scope global primary | grep inet | awk '{ print $2, $3, $4; exit }')
 
         if [ "$DEFAULT_ROUTE_GW" != "" ]; then
             ADD_DEFAULT_ROUTE="sudo ip -f $af r replace default via $DEFAULT_ROUTE_GW dev $to_intf"
@@ -817,12 +829,19 @@
             ADD_OVS_PORT="sudo ovs-vsctl --may-exist add-port $to_intf $from_intf"
         fi
 
+        if [[ "$del_ovs_port" == "True" ]]; then
+            DEL_OVS_PORT="sudo ovs-vsctl --if-exists del-port $from_intf $to_intf"
+        fi
+
         if [[ "$IP_BRD" != "" ]]; then
             IP_DEL="sudo ip addr del $IP_BRD dev $from_intf"
             IP_ADD="sudo ip addr add $IP_BRD dev $to_intf"
+            IP_UP="sudo ip link set $to_intf up"
         fi
 
-        $IP_DEL; $IP_ADD; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
+        # The add/del OVS port calls have to happen either before or
+        # after the address is moved in order to not leave it orphaned.
+        $DEL_OVS_PORT; $IP_DEL; $IP_ADD; $IP_UP; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
     fi
 }
 
@@ -831,14 +850,14 @@
 function cleanup_neutron {
 
     if [[ -n "$OVS_PHYSICAL_BRIDGE" ]]; then
-        _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False "inet"
+        _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False True "inet"
 
         if [[ $(ip -f inet6 a s dev "$OVS_PHYSICAL_BRIDGE" | grep -c 'global') != 0 ]]; then
             # ip(8) wants the prefix length when deleting
             local v6_gateway
             v6_gateway=$(ip -6 a s dev $OVS_PHYSICAL_BRIDGE | grep $IPV6_PUBLIC_NETWORK_GATEWAY | awk '{ print $2 }')
             sudo ip -6 addr del $v6_gateway dev $OVS_PHYSICAL_BRIDGE
-            _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False "inet6"
+            _move_neutron_addresses_route "$OVS_PHYSICAL_BRIDGE" "$PUBLIC_INTERFACE" False False "inet6"
         fi
 
         if is_provider_network && is_ironic_hardware; then
@@ -876,7 +895,10 @@
 function _configure_neutron_common {
     _create_neutron_conf_dir
 
-    cp $NEUTRON_DIR/etc/neutron.conf $NEUTRON_CONF
+    # Uses oslo config generator to generate core sample configuration files
+    (cd $NEUTRON_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    cp $NEUTRON_DIR/etc/neutron.conf.sample $NEUTRON_CONF
 
     Q_POLICY_FILE=$NEUTRON_CONF_DIR/policy.json
     cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
@@ -901,7 +923,9 @@
     Q_PLUGIN_CONF_FILE=$Q_PLUGIN_CONF_PATH/$Q_PLUGIN_CONF_FILENAME
     # NOTE(hichihara): Some neutron vendor plugins were already decomposed and
     # there is no config file in Neutron tree. They should prepare the file in each plugin.
-    if [ -f $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE ]; then
+    if [ -f "$NEUTRON_DIR/$Q_PLUGIN_CONF_FILE.sample" ]; then
+        cp "$NEUTRON_DIR/$Q_PLUGIN_CONF_FILE.sample" /$Q_PLUGIN_CONF_FILE
+    elif [ -f $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE ]; then
         cp $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE /$Q_PLUGIN_CONF_FILE
     fi
 
@@ -909,6 +933,8 @@
     iniset $NEUTRON_CONF DEFAULT state_path $DATA_DIR/neutron
     iniset $NEUTRON_CONF DEFAULT use_syslog $SYSLOG
     iniset $NEUTRON_CONF DEFAULT bind_host $Q_LISTEN_ADDRESS
+    iniset $NEUTRON_CONF oslo_concurrency lock_path $DATA_DIR/neutron/lock
+
     # If addition config files are set, make sure their path name is set as well
     if [[ ${#Q_PLUGIN_EXTRA_CONF_FILES[@]} > 0 && $Q_PLUGIN_EXTRA_CONF_PATH == '' ]]; then
         die $LINENO "Neutron additional plugin config not set.. exiting"
@@ -965,7 +991,7 @@
         return
     fi
 
-    cp $NEUTRON_DIR/etc/l3_agent.ini $NEUTRON_TEST_CONFIG_FILE
+    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $NEUTRON_TEST_CONFIG_FILE
 
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT verbose False
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT debug False
@@ -981,7 +1007,7 @@
 
 function _configure_neutron_dhcp_agent {
 
-    cp $NEUTRON_DIR/etc/dhcp_agent.ini $Q_DHCP_CONF_FILE
+    cp $NEUTRON_DIR/etc/dhcp_agent.ini.sample $Q_DHCP_CONF_FILE
 
     iniset $Q_DHCP_CONF_FILE DEFAULT verbose True
     iniset $Q_DHCP_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1013,7 +1039,7 @@
         neutron_vpn_configure_agent
     fi
 
-    cp $NEUTRON_DIR/etc/l3_agent.ini $Q_L3_CONF_FILE
+    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $Q_L3_CONF_FILE
 
     iniset $Q_L3_CONF_FILE DEFAULT verbose True
     iniset $Q_L3_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1026,15 +1052,15 @@
 
     neutron_plugin_configure_l3_agent
 
-    _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True "inet"
+    _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" True False "inet"
 
     if [[ $(ip -f inet6 a s dev "$PUBLIC_INTERFACE" | grep -c 'global') != 0 ]]; then
-        _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" False "inet6"
+        _move_neutron_addresses_route "$PUBLIC_INTERFACE" "$OVS_PHYSICAL_BRIDGE" False False "inet6"
     fi
 }
 
 function _configure_neutron_metadata_agent {
-    cp $NEUTRON_DIR/etc/metadata_agent.ini $Q_META_CONF_FILE
+    cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $Q_META_CONF_FILE
 
     iniset $Q_META_CONF_FILE DEFAULT verbose True
     iniset $Q_META_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1043,11 +1069,6 @@
     if [[ "$Q_USE_ROOTWRAP_DAEMON" == "True" ]]; then
         iniset $Q_META_CONF_FILE AGENT root_helper_daemon "$Q_RR_DAEMON_COMMAND"
     fi
-
-    # Configures keystone for metadata_agent
-    # The third argument "True" sets auth_url needed to communicate with keystone
-    _neutron_setup_keystone $Q_META_CONF_FILE DEFAULT True
-
 }
 
 function _configure_neutron_ceilometer_notifications {
@@ -1055,8 +1076,12 @@
 }
 
 function _configure_neutron_lbaas {
-    if [ -f $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf ]; then
-        cp $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf $NEUTRON_CONF_DIR
+    # Uses oslo config generator to generate LBaaS sample configuration files
+    (cd $NEUTRON_LBAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    if [ -f $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample ]; then
+        cp $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample $NEUTRON_CONF_DIR/neutron_lbaas.conf
+        iniset $NEUTRON_CONF_DIR/neutron_lbaas.conf service_providers service_provider $DEFAULT_LB_PROVIDER
     fi
     neutron_agent_lbaas_configure_common
     neutron_agent_lbaas_configure_agent
@@ -1076,8 +1101,11 @@
 }
 
 function _configure_neutron_vpn {
-    if [ -f $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf ]; then
-        cp $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf $NEUTRON_CONF_DIR
+    # Uses oslo config generator to generate VPNaaS sample configuration files
+    (cd $NEUTRON_VPNAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+    if [ -f $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample ]; then
+        cp $NEUTRON_VPNAAS_DIR/etc/neutron_vpnaas.conf.sample $NEUTRON_CONF_DIR/neutron_vpnaas.conf
+        iniset $NEUTRON_CONF_DIR/neutron_vpnaas.conf service_providers service_provider $DEFAULT_VPN_PROVIDER
     fi
     neutron_vpn_install_agent_packages
     neutron_vpn_configure_common
@@ -1208,17 +1236,10 @@
     fi
 }
 
-# Configures keystone integration for neutron service and agents
+# Configures keystone integration for neutron service
 function _neutron_setup_keystone {
     local conf_file=$1
     local section=$2
-    local use_auth_url=$3
-
-    # Configures keystone for metadata_agent
-    # metadata_agent needs auth_url to communicate with keystone
-    if [[ "$use_auth_url" == "True" ]]; then
-        iniset $conf_file $section auth_url $KEYSTONE_SERVICE_URI/v2.0
-    fi
 
     create_neutron_cache_dir
     configure_auth_token_middleware $conf_file $Q_ADMIN_USERNAME $NEUTRON_AUTH_CACHE_DIR $section
@@ -1325,7 +1346,7 @@
                 sudo ip addr add $ext_gw_ip/$cidr_len dev $ext_gw_interface
                 sudo ip link set $ext_gw_interface up
             fi
-            ROUTER_GW_IP=`neutron port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F '"' -v subnet_id=$PUB_SUBNET_ID '$4 == subnet_id { print $8; }'`
+            ROUTER_GW_IP=`neutron port-list -c fixed_ips -c device_owner | grep router_gateway | awk -F'ip_address'  '{ print $2 }' | cut -f3 -d\" | tr '\n' ' '`
             die_if_not_set $LINENO ROUTER_GW_IP "Failure retrieving ROUTER_GW_IP"
             sudo ip route replace  $FIXED_RANGE via $ROUTER_GW_IP
         fi
@@ -1356,7 +1377,7 @@
         sudo sysctl -w net.ipv6.conf.all.forwarding=1
         # Configure and enable public bridge
         # Override global IPV6_ROUTER_GW_IP with the true value from neutron
-        IPV6_ROUTER_GW_IP=`neutron port-list -c fixed_ips | grep $ipv6_pub_subnet_id | awk -F '"' -v subnet_id=$ipv6_pub_subnet_id '$4 == subnet_id { print $8; }'`
+        IPV6_ROUTER_GW_IP=`neutron port-list -c fixed_ips | grep $ipv6_pub_subnet_id | awk -F'ip_address' '{ print $2 }' | cut -f3 -d\" | tr '\n' ' '`
         die_if_not_set $LINENO IPV6_ROUTER_GW_IP "Failure retrieving IPV6_ROUTER_GW_IP"
 
         if is_neutron_ovs_base_plugin; then
@@ -1498,7 +1519,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_NEUTRON
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/neutron_plugins/bigswitch_floodlight b/lib/neutron_plugins/bigswitch_floodlight
index f52105e..586ded7 100644
--- a/lib/neutron_plugins/bigswitch_floodlight
+++ b/lib/neutron_plugins/bigswitch_floodlight
@@ -4,7 +4,7 @@
 # ------------------------------------
 
 # Save trace setting
-BS_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_BIGSWITCH=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/neutron_plugins/ovs_base
@@ -75,4 +75,4 @@
 }
 
 # Restore xtrace
-$BS_XTRACE
+$_XTRACE_NEUTRON_BIGSWITCH
diff --git a/lib/neutron_plugins/brocade b/lib/neutron_plugins/brocade
index 953360e..6ba0a66 100644
--- a/lib/neutron_plugins/brocade
+++ b/lib/neutron_plugins/brocade
@@ -4,7 +4,7 @@
 # ----------------------
 
 # Save trace setting
-BRCD_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_BROCADE=$(set +o | grep xtrace)
 set +o xtrace
 
 function is_neutron_ovs_base_plugin {
@@ -81,4 +81,4 @@
 }
 
 # Restore xtrace
-$BRCD_XTRACE
+$_XTRACE_NEUTRON_BROCADE
diff --git a/lib/neutron_plugins/cisco b/lib/neutron_plugins/cisco
index 7d0cf1a..fc2cb8a 100644
--- a/lib/neutron_plugins/cisco
+++ b/lib/neutron_plugins/cisco
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-CISCO_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_CISCO=$(set +o | grep xtrace)
 set +o xtrace
 
 # Scecify the VSM parameters
@@ -154,4 +154,4 @@
 }
 
 # Restore xtrace
-$CISCO_XTRACE
+$_XTRACE_NEUTRON_CISCO
diff --git a/lib/neutron_plugins/embrane b/lib/neutron_plugins/embrane
index 2028496..385dab8 100644
--- a/lib/neutron_plugins/embrane
+++ b/lib/neutron_plugins/embrane
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-EMBR_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_EMBR=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/neutron_plugins/openvswitch
@@ -39,4 +39,5 @@
 }
 
 # Restore xtrace
-$EMBR_XTRACE
+$_XTRACE_NEUTRON_EMBR
+
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index f28bcfe..096722b 100644
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -4,7 +4,7 @@
 # -----------------------------
 
 # Save trace setting
-PLUGIN_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_LB=$(set +o | grep xtrace)
 set +o xtrace
 
 function neutron_lb_cleanup {
@@ -93,4 +93,4 @@
 }
 
 # Restore xtrace
-$PLUGIN_XTRACE
+$_XTRACE_NEUTRON_LB
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index ace5335..30e1b03 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -4,7 +4,7 @@
 # ------------------------------
 
 # Save trace setting
-ML2_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_ML2=$(set +o | grep xtrace)
 set +o xtrace
 
 # Enable this to simply and quickly enable tunneling with ML2.
@@ -137,4 +137,4 @@
 }
 
 # Restore xtrace
-$ML2_XTRACE
+$_XTRACE_NEUTRON_ML2
diff --git a/lib/neutron_plugins/nec b/lib/neutron_plugins/nec
deleted file mode 100644
index 9ea7338..0000000
--- a/lib/neutron_plugins/nec
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-# This file is needed so Q_PLUGIN=nec will work.
-
-# FIXME(amotoki): This function should not be here, but unfortunately
-# devstack calls it before the external plugins are fetched
-function has_neutron_plugin_security_group {
-    # 0 means True here
-    return 0
-}
diff --git a/lib/neutron_plugins/nuage b/lib/neutron_plugins/nuage
index 9e5307b..61e634e 100644
--- a/lib/neutron_plugins/nuage
+++ b/lib/neutron_plugins/nuage
@@ -4,7 +4,7 @@
 # ----------------------
 
 # Save trace setting
-NU_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_NU=$(set +o | grep xtrace)
 set +o xtrace
 
 function neutron_plugin_create_nova_conf {
@@ -66,4 +66,4 @@
 }
 
 # Restore xtrace
-$NU_XTRACE
+$_XTRACE_NEUTRON_NU
diff --git a/lib/neutron_plugins/openvswitch b/lib/neutron_plugins/openvswitch
index 891ab49..130eaac 100644
--- a/lib/neutron_plugins/openvswitch
+++ b/lib/neutron_plugins/openvswitch
@@ -7,7 +7,7 @@
 # which has been removed in Juno.
 
 # Save trace setting
-OVS_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_OVS=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/neutron_plugins/openvswitch_agent
@@ -56,4 +56,5 @@
 }
 
 # Restore xtrace
-$OVS_XTRACE
+$_XTRACE_NEUTRON_OVS
+
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 6a33393..b1acacd 100644
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -4,7 +4,7 @@
 # -----------------------------
 
 # Save trace setting
-OVSA_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_OVSL2=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/neutron_plugins/ovs_base
@@ -132,4 +132,4 @@
 }
 
 # Restore xtrace
-$OVSA_XTRACE
+$_XTRACE_NEUTRON_OVSL2
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index d3fd198..59c7737 100644
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -4,7 +4,7 @@
 # -------------------------------------
 
 # Save trace setting
-OVSB_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_OVS_BASE=$(set +o | grep xtrace)
 set +o xtrace
 
 OVS_BRIDGE=${OVS_BRIDGE:-br-int}
@@ -67,6 +67,7 @@
         restart_service openvswitch-switch
     elif is_fedora; then
         restart_service openvswitch
+        sudo systemctl enable openvswitch
     elif is_suse; then
         restart_service openvswitch-switch
     fi
@@ -114,4 +115,4 @@
 }
 
 # Restore xtrace
-$OVSB_XTRACE
+$_XTRACE_NEUTRON_OVS_BASE
diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall
index 3496da8..2b7f32d 100644
--- a/lib/neutron_plugins/services/firewall
+++ b/lib/neutron_plugins/services/firewall
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-FW_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_FIREWALL=$(set +o | grep xtrace)
 set +o xtrace
 
 FWAAS_PLUGIN=neutron_fwaas.services.firewall.fwaas_plugin.FirewallPlugin
@@ -14,8 +14,11 @@
 }
 
 function neutron_fwaas_configure_driver {
+    # Uses oslo config generator to generate FWaaS sample configuration files
+    (cd $NEUTRON_FWAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+
     FWAAS_DRIVER_CONF_FILENAME=/etc/neutron/fwaas_driver.ini
-    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini $FWAAS_DRIVER_CONF_FILENAME
+    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini.sample $FWAAS_DRIVER_CONF_FILENAME
 
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas enabled True
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver"
@@ -26,4 +29,4 @@
 }
 
 # Restore xtrace
-$FW_XTRACE
+$_XTRACE_NEUTRON_FIREWALL
diff --git a/lib/neutron_plugins/services/loadbalancer b/lib/neutron_plugins/services/loadbalancer
index 7865f6f..30e9480 100644
--- a/lib/neutron_plugins/services/loadbalancer
+++ b/lib/neutron_plugins/services/loadbalancer
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-LB_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_LB=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -28,7 +28,7 @@
 
     LBAAS_AGENT_CONF_FILENAME="$LBAAS_AGENT_CONF_PATH/lbaas_agent.ini"
 
-    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini $LBAAS_AGENT_CONF_FILENAME
+    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini.sample $LBAAS_AGENT_CONF_FILENAME
 
     # ovs_use_veth needs to be set before the plugin configuration
     # occurs to allow plugins to override the setting.
@@ -48,4 +48,4 @@
 }
 
 # Restore xtrace
-$LB_XTRACE
+$_XTRACE_NEUTRON_LB
diff --git a/lib/neutron_plugins/services/metering b/lib/neutron_plugins/services/metering
index c75ab19..5b32468 100644
--- a/lib/neutron_plugins/services/metering
+++ b/lib/neutron_plugins/services/metering
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-METER_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NETURON_METER=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -21,7 +21,7 @@
 
     METERING_AGENT_CONF_FILENAME="$METERING_AGENT_CONF_PATH/metering_agent.ini"
 
-    cp $NEUTRON_DIR/etc/metering_agent.ini $METERING_AGENT_CONF_FILENAME
+    cp $NEUTRON_DIR/etc/metering_agent.ini.sample $METERING_AGENT_CONF_FILENAME
 }
 
 function neutron_metering_stop {
@@ -29,4 +29,5 @@
 }
 
 # Restore xtrace
-$METER_XTRACE
+$_XTRACE_NETURON_METER
+
diff --git a/lib/neutron_plugins/services/vpn b/lib/neutron_plugins/services/vpn
index c0e7457..e790913 100644
--- a/lib/neutron_plugins/services/vpn
+++ b/lib/neutron_plugins/services/vpn
@@ -4,7 +4,7 @@
 # ---------------------------
 
 # Save trace setting
-VPN_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_VPN=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -29,7 +29,9 @@
 }
 
 function neutron_vpn_configure_agent {
-    cp $NEUTRON_VPNAAS_DIR/etc/vpn_agent.ini $Q_VPN_CONF_FILE
+    # Uses oslo config generator to generate LBaaS sample configuration files
+    (cd $NEUTRON_VPNAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+    cp $NEUTRON_VPNAAS_DIR/etc/vpn_agent.ini.sample $Q_VPN_CONF_FILE
     if [[ "$IPSEC_PACKAGE" == "strongswan" ]]; then
         iniset_multiline $Q_VPN_CONF_FILE vpnagent vpn_device_driver neutron_vpnaas.services.vpn.device_drivers.strongswan_ipsec.StrongSwanDriver
         if is_fedora; then
@@ -53,4 +55,4 @@
 }
 
 # Restore xtrace
-$VPN_XTRACE
+$_XTRACE_NEUTRON_VPN
diff --git a/lib/neutron_thirdparty/bigswitch_floodlight b/lib/neutron_thirdparty/bigswitch_floodlight
index e3f4689..45a4f2e 100644
--- a/lib/neutron_thirdparty/bigswitch_floodlight
+++ b/lib/neutron_thirdparty/bigswitch_floodlight
@@ -4,7 +4,7 @@
 # ------------------------------------------
 
 # Save trace setting
-BS3_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NEUTRON_BIGSWITCH=$(set +o | grep xtrace)
 set +o xtrace
 
 BS_FL_CONTROLLERS_PORT=${BS_FL_CONTROLLERS_PORT:-localhost:80}
@@ -51,4 +51,4 @@
 }
 
 # Restore xtrace
-$BS3_XTRACE
+$_XTRACE_NEUTRON_BIGSWITCH
diff --git a/lib/nova b/lib/nova
index ba05f53..62481ed 100644
--- a/lib/nova
+++ b/lib/nova
@@ -25,7 +25,7 @@
 # - cleanup_nova
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_NOVA=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -98,6 +98,10 @@
 # should work in most cases.
 SCHEDULER=${SCHEDULER:-nova.scheduler.filter_scheduler.FilterScheduler}
 
+# The following FILTERS contains SameHostFilter and DifferentHostFilter with
+# the default filters.
+FILTERS="RetryFilter,AvailabilityZoneFilter,RamFilter,DiskFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,ServerGroupAntiAffinityFilter,ServerGroupAffinityFilter,SameHostFilter,DifferentHostFilter"
+
 QEMU_CONF=/etc/libvirt/qemu.conf
 
 # Set default defaults here as some hypervisor drivers override these
@@ -242,7 +246,6 @@
 function _cleanup_nova_apache_wsgi {
     sudo rm -f $NOVA_WSGI_DIR/*
     sudo rm -f $(apache_site_config_for nova-api)
-    sudo rm -f $(apache_site_config_for nova-ec2-api)
     sudo rm -f $(apache_site_config_for nova-metadata)
 }
 
@@ -252,15 +255,12 @@
 
     local nova_apache_conf
     nova_apache_conf=$(apache_site_config_for nova-api)
-    local nova_ec2_apache_conf
-    nova_ec2_apache_conf=$(apache_site_config_for nova-ec2-api)
     local nova_metadata_apache_conf
     nova_metadata_apache_conf=$(apache_site_config_for nova-metadata)
     local nova_ssl=""
     local nova_certfile=""
     local nova_keyfile=""
     local nova_api_port=$NOVA_SERVICE_PORT
-    local nova_ec2_api_port=$EC2_SERVICE_PORT
     local nova_metadata_port=$METADATA_SERVICE_PORT
     local venv_path=""
 
@@ -275,7 +275,6 @@
 
     # copy proxy vhost and wsgi helper files
     sudo cp $NOVA_DIR/nova/wsgi/nova-api.py $NOVA_WSGI_DIR/nova-api
-    sudo cp $NOVA_DIR/nova/wsgi/nova-ec2-api.py $NOVA_WSGI_DIR/nova-ec2-api
     sudo cp $NOVA_DIR/nova/wsgi/nova-metadata.py $NOVA_WSGI_DIR/nova-metadata
 
     sudo cp $FILES/apache-nova-api.template $nova_apache_conf
@@ -291,19 +290,6 @@
         s|%APIWORKERS%|$API_WORKERS|g
     " -i $nova_apache_conf
 
-    sudo cp $FILES/apache-nova-ec2-api.template $nova_ec2_apache_conf
-    sudo sed -e "
-        s|%PUBLICPORT%|$nova_ec2_api_port|g;
-        s|%APACHE_NAME%|$APACHE_NAME|g;
-        s|%PUBLICWSGI%|$NOVA_WSGI_DIR/nova-ec2-api|g;
-        s|%SSLENGINE%|$nova_ssl|g;
-        s|%SSLCERTFILE%|$nova_certfile|g;
-        s|%SSLKEYFILE%|$nova_keyfile|g;
-        s|%USER%|$STACK_USER|g;
-        s|%VIRTUALENV%|$venv_path|g
-        s|%APIWORKERS%|$API_WORKERS|g
-    " -i $nova_ec2_apache_conf
-
     sudo cp $FILES/apache-nova-metadata.template $nova_metadata_apache_conf
     sudo sed -e "
         s|%PUBLICPORT%|$nova_metadata_port|g;
@@ -461,26 +447,10 @@
             # swift through the s3 api.
             get_or_add_user_project_role ResellerAdmin nova $SERVICE_TENANT_NAME
         fi
-
-        # EC2
-        if [[ "$KEYSTONE_CATALOG_BACKEND" = "sql" ]]; then
-            local nova_ec2_api_url
-            if [[ "$NOVA_USE_MOD_WSGI" == "False" ]]; then
-                nova_ec2_api_url="$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:$EC2_SERVICE_PORT/"
-            else
-                nova_ec2_api_url="$EC2_SERVICE_PROTOCOL://$SERVICE_HOST/ec2"
-            fi
-            get_or_create_service "ec2" "ec2" "EC2 Compatibility Layer"
-            get_or_create_endpoint "ec2" \
-                "$REGION_NAME" \
-                "$nova_ec2_api_url" \
-                "$nova_ec2_api_url" \
-                "$nova_ec2_api_url"
-        fi
     fi
 
     # S3
-    if is_service_enabled n-obj swift3; then
+    if is_service_enabled swift3; then
         if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
 
             get_or_create_service "s3" "s3" "S3"
@@ -507,7 +477,7 @@
     iniset $NOVA_CONF DEFAULT api_paste_config "$NOVA_API_PASTE_INI"
     iniset $NOVA_CONF DEFAULT rootwrap_config "$NOVA_CONF_DIR/rootwrap.conf"
     iniset $NOVA_CONF DEFAULT scheduler_driver "$SCHEDULER"
-    iniset $NOVA_CONF DEFAULT dhcpbridge_flagfile "$NOVA_CONF"
+    iniset $NOVA_CONF DEFAULT scheduler_default_filters "$FILTERS"
     iniset $NOVA_CONF DEFAULT force_dhcp_release "True"
     iniset $NOVA_CONF DEFAULT default_floating_pool "$PUBLIC_NETWORK_NAME"
     iniset $NOVA_CONF DEFAULT s3_host "$SERVICE_HOST"
@@ -522,7 +492,6 @@
     iniset $NOVA_CONF api_database connection `database_connection_url nova_api`
     iniset $NOVA_CONF DEFAULT instance_name_template "${INSTANCE_NAME_PREFIX}%08x"
     iniset $NOVA_CONF DEFAULT osapi_compute_listen "$NOVA_SERVICE_LISTEN_ADDRESS"
-    iniset $NOVA_CONF DEFAULT ec2_listen "$NOVA_SERVICE_LISTEN_ADDRESS"
     iniset $NOVA_CONF DEFAULT metadata_listen "$NOVA_SERVICE_LISTEN_ADDRESS"
     iniset $NOVA_CONF DEFAULT s3_listen "$NOVA_SERVICE_LISTEN_ADDRESS"
 
@@ -629,12 +598,10 @@
     fi
 
     iniset $NOVA_CONF DEFAULT ec2_dmz_host "$EC2_DMZ_HOST"
-    iniset $NOVA_CONF DEFAULT keystone_ec2_url $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v2.0/ec2tokens
     iniset_rpc_backend nova $NOVA_CONF
     iniset $NOVA_CONF glance api_servers "${GLANCE_SERVICE_PROTOCOL}://${GLANCE_HOSTPORT}"
 
     iniset $NOVA_CONF DEFAULT osapi_compute_workers "$API_WORKERS"
-    iniset $NOVA_CONF DEFAULT ec2_workers "$API_WORKERS"
     iniset $NOVA_CONF DEFAULT metadata_workers "$API_WORKERS"
     # don't let the conductor get out of control now that we're using a pure python db driver
     iniset $NOVA_CONF conductor workers "$API_WORKERS"
@@ -660,14 +627,28 @@
         iniset $NOVA_CONF DEFAULT enabled_ssl_apis "$NOVA_ENABLED_APIS"
     fi
 
-    if is_service_enabled tls-proxy; then
-        iniset $NOVA_CONF DEFAULT ec2_listen_port $EC2_SERVICE_PORT_INT
-    fi
-
     if is_service_enabled n-sproxy; then
         iniset $NOVA_CONF serial_console serialproxy_host "$NOVA_SERVICE_LISTEN_ADDRESS"
         iniset $NOVA_CONF serial_console enabled True
     fi
+    iniset $NOVA_CONF DEFAULT graceful_shutdown_timeout "$SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT"
+
+    # Setup logging for nova-dhcpbridge command line
+    sudo cp "$NOVA_CONF" "$NOVA_CONF_DIR/nova-dhcpbridge.conf"
+
+    local service="n-dhcp"
+    local logfile="${service}.log.${CURRENT_LOG_TIME}"
+    local real_logfile="${LOGDIR}/${logfile}"
+    if [[ -n ${LOGDIR} ]]; then
+        bash -c "cd '$LOGDIR' && ln -sf '$logfile' ${service}.log"
+        iniset "$NOVA_CONF_DIR/nova-dhcpbridge.conf" DEFAULT log_file "$real_logfile"
+        if [[ -n ${SCREEN_LOGDIR} ]]; then
+            # Drop the backward-compat symlink
+            ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${service}.log
+        fi
+    fi
+
+    iniset $NOVA_CONF DEFAULT dhcpbridge_flagfile "$NOVA_CONF_DIR/nova-dhcpbridge.conf"
 }
 
 function init_nova_cells {
@@ -816,11 +797,9 @@
     enabled_site_file=$(apache_site_config_for nova-api)
     if [ -f ${enabled_site_file} ] && [ "$NOVA_USE_MOD_WSGI" == "True" ]; then
         enable_apache_site nova-api
-        enable_apache_site nova-ec2-api
         enable_apache_site nova-metadata
         restart_apache_server
         tail_log nova-api /var/log/$APACHE_NAME/nova-api.log
-        tail_log nova-ec2-api /var/log/$APACHE_NAME/nova-ec2-api.log
         tail_log nova-metadata /var/log/$APACHE_NAME/nova-metadata.log
     else
         run_process n-api "$NOVA_BIN_DIR/nova-api"
@@ -906,11 +885,6 @@
     run_process n-cauth "$NOVA_BIN_DIR/nova-consoleauth --config-file $api_cell_conf"
     run_process n-sproxy "$NOVA_BIN_DIR/nova-serialproxy --config-file $api_cell_conf"
 
-    # Starting the nova-objectstore only if swift3 service is not enabled.
-    # Swift will act as s3 objectstore.
-    is_service_enabled swift3 || \
-        run_process n-obj "$NOVA_BIN_DIR/nova-objectstore --config-file $api_cell_conf"
-
     export PATH=$old_path
 }
 
@@ -936,7 +910,6 @@
 function stop_nova_rest {
     if [ "$NOVA_USE_MOD_WSGI" == "True" ]; then
         disable_apache_site nova-api
-        disable_apache_site nova-ec2-api
         disable_apache_site nova-metadata
         restart_apache_server
     else
@@ -945,7 +918,7 @@
     # Kill the nova screen windows
     # Some services are listed here twice since more than one instance
     # of a service may be running in certain configs.
-    for serv in n-api n-crt n-net n-sch n-novnc n-xvnc n-cauth n-spice n-cond n-cell n-cell n-api-meta n-obj n-sproxy; do
+    for serv in n-api n-crt n-net n-sch n-novnc n-xvnc n-cauth n-spice n-cond n-cell n-cell n-api-meta n-sproxy; do
         stop_process $serv
     done
 }
@@ -958,7 +931,7 @@
 
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_NOVA
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 045fc8b..0afdad8 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -8,7 +8,7 @@
 # ``STACK_USER`` has to be defined
 
 # Save trace setting
-LV_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NOVA_FN_LIBVIRT=$(set +o | grep xtrace)
 set +o xtrace
 
 # Defaults
@@ -38,7 +38,10 @@
         fi
         #pip_install_gr <there-si-no-guestfs-in-pypi>
     elif is_fedora || is_suse; then
-        install_package kvm
+        # On "KVM for IBM z Systems", kvm does not have its own package
+        if [[ ! ${DISTRO} =~ "kvmibm1" ]]; 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
@@ -134,7 +137,7 @@
 
 
 # Restore xtrace
-$LV_XTRACE
+$_XTRACE_NOVA_FN_LIBVIRT
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-fake b/lib/nova_plugins/hypervisor-fake
index 3180d91..2434dce 100644
--- a/lib/nova_plugins/hypervisor-fake
+++ b/lib/nova_plugins/hypervisor-fake
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_VIRTFAKE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -72,7 +72,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_VIRTFAKE
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index b9e286d..c6ed85d 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_HYP_IRONIC=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/nova_plugins/functions-libvirt
@@ -81,7 +81,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_HYP_IRONIC
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index c54a716..8bbaa21 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NOVA_LIBVIRT=$(set +o | grep xtrace)
 set +o xtrace
 
 source $TOP_DIR/lib/nova_plugins/functions-libvirt
@@ -105,7 +105,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_NOVA_LIBVIRT
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-openvz b/lib/nova_plugins/hypervisor-openvz
index cce36b8..58ab5c1 100644
--- a/lib/nova_plugins/hypervisor-openvz
+++ b/lib/nova_plugins/hypervisor-openvz
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_OPENVZ=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -62,7 +62,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_OPENVZ
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-vsphere b/lib/nova_plugins/hypervisor-vsphere
index 698f836..7c08bc9 100644
--- a/lib/nova_plugins/hypervisor-vsphere
+++ b/lib/nova_plugins/hypervisor-vsphere
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_NOVA_VSPHERE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -64,7 +64,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_NOVA_VSPHERE
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/nova_plugins/hypervisor-xenserver b/lib/nova_plugins/hypervisor-xenserver
index e097990..3eb9149 100644
--- a/lib/nova_plugins/hypervisor-xenserver
+++ b/lib/nova_plugins/hypervisor-xenserver
@@ -17,7 +17,7 @@
 # cleanup_nova_hypervisor - remove transient data and cache
 
 # Save trace setting
-MY_XTRACE=$(set +o | grep xtrace)
+_XTRACE_XENSERVER=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -111,7 +111,7 @@
 
 
 # Restore xtrace
-$MY_XTRACE
+$_XTRACE_XENSERVER
 
 # Local variables:
 # mode: shell-script
diff --git a/lib/oslo b/lib/oslo
index 56615fa..3d6fbb3 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -16,7 +16,7 @@
 # - install_oslo
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_OSLO=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -95,7 +95,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_OSLO
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 298dcb6..05e303e 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -21,7 +21,7 @@
 # of this file which is a standard interface.
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_RPC_BACKEND=$(set +o | grep xtrace)
 set +o xtrace
 
 # Functions
@@ -47,6 +47,9 @@
     if is_service_enabled rabbit; then
         # Install rabbitmq-server
         install_package rabbitmq-server
+        if is_fedora; then
+            sudo systemctl enable rabbitmq-server
+        fi
     fi
 }
 
@@ -141,7 +144,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_RPC_BACKEND
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/stack b/lib/stack
index 7d98604..f09ddce 100644
--- a/lib/stack
+++ b/lib/stack
@@ -19,6 +19,7 @@
 function stack_install_service {
     local service=$1
     if type install_${service} >/dev/null 2>&1; then
+        # FIXME(dhellmann): Needs to be python3-aware at some point.
         if [[ ${USE_VENV} = True && -n ${PROJECT_VENV[$service]:-} ]]; then
             rm -rf ${PROJECT_VENV[$service]}
             source $TOP_DIR/tools/build_venv.sh ${PROJECT_VENV[$service]} ${ADDITIONAL_VENV_PACKAGES//,/ }
diff --git a/lib/swift b/lib/swift
index d7ccc24..b596142 100644
--- a/lib/swift
+++ b/lib/swift
@@ -24,7 +24,7 @@
 # - _cleanup_swift_apache_wsgi
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_LIB_SWIFT=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -823,7 +823,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_LIB_SWIFT
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/tempest b/lib/tempest
index a824b52..329308c 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -35,10 +35,9 @@
 #
 # - install_tempest
 # - configure_tempest
-# - init_tempest
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_TEMPEST=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -67,9 +66,6 @@
 # have tempest installed in DevStack by default.
 INSTALL_TEMPEST=${INSTALL_TEMPEST:-"True"}
 
-BOTO_MATERIALS_PATH="$FILES/images/s3-materials/cirros-${CIRROS_VERSION}"
-BOTO_CONF=/etc/boto.cfg
-
 # Cinder/Volume variables
 TEMPEST_VOLUME_DRIVER=${TEMPEST_VOLUME_DRIVER:-default}
 TEMPEST_DEFAULT_VOLUME_VENDOR="Open Source"
@@ -131,7 +127,6 @@
     local flavor_lines
     local public_network_id
     local public_router_id
-    local boto_instance_type="m1.tiny"
     local ssh_connect_method="fixed"
 
     # Save IFS
@@ -196,29 +191,26 @@
     if is_service_enabled nova; then
         # If ``DEFAULT_INSTANCE_TYPE`` is not declared, use the new behavior
         # Tempest creates its own instance types
+        available_flavors=$(nova flavor-list)
         if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
-            available_flavors=$(nova flavor-list)
             if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then
                 nova flavor-create m1.nano 42 64 0 1
             fi
             flavor_ref=42
-            boto_instance_type=m1.nano
             if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then
                 nova flavor-create m1.micro 84 128 0 1
             fi
             flavor_ref_alt=84
         else
             # Check Nova for existing flavors, if ``DEFAULT_INSTANCE_TYPE`` is set use it.
-            boto_instance_type=$DEFAULT_INSTANCE_TYPE
-            flavor_lines=`nova flavor-list`
             IFS=$'\r\n'
             flavors=""
-            for line in $flavor_lines; do
+            for line in $available_flavors; do
                 f=$(echo $line | awk "/ $DEFAULT_INSTANCE_TYPE / { print \$2 }")
                 flavors="$flavors $f"
             done
 
-            for line in $flavor_lines; do
+            for line in $available_flavors; do
                 flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
             done
 
@@ -255,15 +247,6 @@
             awk '{print $2}')
     fi
 
-    EC2_URL=$(get_endpoint_url ec2 public || true)
-    if [[ -z $EC2_URL ]]; then
-        EC2_URL="$EC2_SERVICE_PROTOCOL://$SERVICE_HOST:8773/"
-    fi
-    S3_URL=$(get_endpoint_url s3 public || true)
-    if [[ -z $S3_URL ]]; then
-        S3_URL="http://$SERVICE_HOST:${S3_SERVICE_PORT:-3333}"
-    fi
-
     iniset $TEMPEST_CONFIG DEFAULT use_syslog $SYSLOG
 
     # Oslo
@@ -276,24 +259,16 @@
     # Timeouts
     iniset $TEMPEST_CONFIG compute build_timeout $BUILD_TIMEOUT
     iniset $TEMPEST_CONFIG volume build_timeout $BUILD_TIMEOUT
-    iniset $TEMPEST_CONFIG boto build_timeout $BUILD_TIMEOUT
-    iniset $TEMPEST_CONFIG boto http_socket_timeout 5
 
     # Identity
     iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
     iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_URI_V3"
-    iniset $TEMPEST_CONFIG identity username $TEMPEST_USERNAME
-    iniset $TEMPEST_CONFIG identity password "$password"
-    iniset $TEMPEST_CONFIG identity tenant_name $TEMPEST_TENANT_NAME
-    iniset $TEMPEST_CONFIG identity alt_username $ALT_USERNAME
-    iniset $TEMPEST_CONFIG identity alt_password "$password"
-    iniset $TEMPEST_CONFIG identity alt_tenant_name $ALT_TENANT_NAME
     if [[ "$TEMPEST_HAS_ADMIN" == "True" ]]; then
-        iniset $TEMPEST_CONFIG identity admin_username $ADMIN_USERNAME
-        iniset $TEMPEST_CONFIG identity admin_password "$password"
-        iniset $TEMPEST_CONFIG identity admin_tenant_name $ADMIN_TENANT_NAME
-        iniset $TEMPEST_CONFIG identity admin_tenant_id $ADMIN_TENANT_ID
-        iniset $TEMPEST_CONFIG identity admin_domain_name $ADMIN_DOMAIN_NAME
+        iniset $TEMPEST_CONFIG auth admin_username $ADMIN_USERNAME
+        iniset $TEMPEST_CONFIG auth admin_password "$password"
+        iniset $TEMPEST_CONFIG auth admin_tenant_name $ADMIN_TENANT_NAME
+        iniset $TEMPEST_CONFIG auth admin_tenant_id $ADMIN_TENANT_ID
+        iniset $TEMPEST_CONFIG auth admin_domain_name $ADMIN_DOMAIN_NAME
     fi
     if [ "$ENABLE_IDENTITY_V2" == "False" ]; then
         # Only Identity v3 is available; then skip Identity API v2 tests
@@ -323,16 +298,15 @@
 
     # Compute
     iniset $TEMPEST_CONFIG compute ssh_user ${DEFAULT_INSTANCE_USER:-cirros} # DEPRECATED
-    iniset $TEMPEST_CONFIG compute network_for_ssh $PRIVATE_NETWORK_NAME
-    iniset $TEMPEST_CONFIG compute ip_version_for_ssh 4
-    iniset $TEMPEST_CONFIG compute ssh_timeout $BUILD_TIMEOUT
     iniset $TEMPEST_CONFIG compute image_ref $image_uuid
-    iniset $TEMPEST_CONFIG compute image_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
     iniset $TEMPEST_CONFIG compute image_ref_alt $image_uuid_alt
     iniset $TEMPEST_CONFIG compute image_alt_ssh_user ${ALT_INSTANCE_USER:-cirros}
     iniset $TEMPEST_CONFIG compute flavor_ref $flavor_ref
     iniset $TEMPEST_CONFIG compute flavor_ref_alt $flavor_ref_alt
     iniset $TEMPEST_CONFIG compute ssh_connect_method $ssh_connect_method
+    # set the equiv validation option here as well to ensure they are
+    # in sync. They shouldn't be separate options.
+    iniset $TEMPEST_CONFIG validation connect_method $ssh_connect_method
     if [[ ! $(is_service_enabled n-cell) && ! $(is_service_enabled neutron) ]]; then
         iniset $TEMPEST_CONFIG compute fixed_network_name $PRIVATE_NETWORK_NAME
     fi
@@ -361,6 +335,30 @@
         compute_api_extensions=$(remove_disabled_extensions $compute_api_extensions $DISABLE_COMPUTE_API_EXTENSIONS)
     fi
 
+    # Set the microversion range for compute tests.
+    # This is used to run the Nova microversions tests.
+    # Setting [None, latest] range of microversion which allow Tempest to run all microversions tests.
+    # NOTE- To avoid microversion tests failure on stable branch, we need to change "tempest_compute_max_microversion"
+    #       for stable branch on each release which should be changed from "latest" to max supported version of that release.
+    local tempest_compute_min_microversion=${TEMPEST_COMPUTE_MIN_MICROVERSION:-None}
+    local tempest_compute_max_microversion=${TEMPEST_COMPUTE_MAX_MICROVERSION:-"latest"}
+    # Reset microversions to None where v2.0 is running which does not support microversion.
+    # Both "None" means no microversion testing.
+    if [[ "$TEMPEST_COMPUTE_TYPE" == "compute_legacy" ]]; then
+        tempest_compute_min_microversion=None
+        tempest_compute_max_microversion=None
+    fi
+    if [ "$tempest_compute_min_microversion" == "None" ]; then
+        inicomment $TEMPEST_CONFIG compute-feature-enabled min_microversion
+    else
+        iniset $TEMPEST_CONFIG compute-feature-enabled min_microversion $tempest_compute_min_microversion
+    fi
+    if [ "$tempest_compute_max_microversion" == "None" ]; then
+        inicomment $TEMPEST_CONFIG compute-feature-enabled max_microversion
+    else
+        iniset $TEMPEST_CONFIG compute-feature-enabled max_microversion $tempest_compute_max_microversion
+    fi
+
     iniset $TEMPEST_CONFIG compute-feature-enabled resize True
     iniset $TEMPEST_CONFIG compute-feature-enabled live_migration ${LIVE_MIGRATION_AVAILABLE:-False}
     iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
@@ -409,16 +407,6 @@
     fi
     iniset $TEMPEST_CONFIG network-feature-enabled api_extensions $network_api_extensions
 
-    # boto
-    iniset $TEMPEST_CONFIG boto ec2_url "$EC2_URL"
-    iniset $TEMPEST_CONFIG boto s3_url "$S3_URL"
-    iniset $TEMPEST_CONFIG boto s3_materials_path "$BOTO_MATERIALS_PATH"
-    iniset $TEMPEST_CONFIG boto ari_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-initrd.manifest.xml
-    iniset $TEMPEST_CONFIG boto ami_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-blank.img.manifest.xml
-    iniset $TEMPEST_CONFIG boto aki_manifest cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-vmlinuz.manifest.xml
-    iniset $TEMPEST_CONFIG boto instance_type "$boto_instance_type"
-    iniset $TEMPEST_CONFIG boto http_socket_timeout 30
-
     # Orchestration Tests
     if is_service_enabled heat; then
         if [[ ! -z "$HEAT_CFN_IMAGE_URL" ]]; then
@@ -460,12 +448,18 @@
 
     # Validation
     iniset $TEMPEST_CONFIG validation run_validation ${TEMPEST_RUN_VALIDATION:-False}
+    iniset $TEMPEST_CONFIG validation ip_version_for_ssh 4
+    iniset $TEMPEST_CONFIG validation ssh_timeout $BUILD_TIMEOUT
+    iniset $TEMPEST_CONFIG validation image_ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
+    iniset $TEMPEST_CONFIG validation network_for_ssh $PRIVATE_NETWORK_NAME
 
     # Volume
     # TODO(dkranz): Remove the bootable flag when Juno is end of life.
     iniset $TEMPEST_CONFIG volume-feature-enabled bootable True
     # TODO(jordanP): Remove the extend_with_snapshot flag when Juno is end of life.
     iniset $TEMPEST_CONFIG volume-feature-enabled extend_with_snapshot True
+    # TODO(obutenko): Remove the incremental_backup_force flag when Kilo and Juno is end of life.
+    iniset $TEMPEST_CONFIG volume-feature-enabled incremental_backup_force True
 
     local volume_api_extensions=${VOLUME_API_EXTENSIONS:-"all"}
     if [[ ! -z "$DISABLE_VOLUME_API_EXTENSIONS" ]]; then
@@ -503,7 +497,6 @@
 
     # Dashboard
     iniset $TEMPEST_CONFIG dashboard dashboard_url "http://$SERVICE_HOST/"
-    iniset $TEMPEST_CONFIG dashboard login_url "http://$SERVICE_HOST/auth/login/"
 
     # CLI
     iniset $TEMPEST_CONFIG cli cli_dir $NOVA_BIN_DIR
@@ -511,7 +504,8 @@
     # Baremetal
     if [ "$VIRT_DRIVER" = "ironic" ] ; then
         iniset $TEMPEST_CONFIG baremetal driver_enabled True
-        iniset $TEMPEST_CONFIG baremetal unprovision_timeout 300
+        iniset $TEMPEST_CONFIG baremetal unprovision_timeout $BUILD_TIMEOUT
+        iniset $TEMPEST_CONFIG baremetal active_timeout $BUILD_TIMEOUT
         iniset $TEMPEST_CONFIG baremetal deploy_img_dir $FILES
         iniset $TEMPEST_CONFIG baremetal node_uuid $IRONIC_NODE_UUID
         iniset $TEMPEST_CONFIG compute-feature-enabled change_password False
@@ -555,12 +549,6 @@
         iniset $TEMPEST_CONFIG service_available cinder "False"
     fi
 
-    if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
-        # Use the ``BOTO_CONFIG`` environment variable to point to this file
-        iniset -sudo $BOTO_CONF Boto ca_certificates_file $SSL_BUNDLE_FILE
-        sudo chown $STACK_USER $BOTO_CONF
-    fi
-
     # Auth
     iniset $TEMPEST_CONFIG auth tempest_roles "Member"
     if [[ $TEMPEST_USE_TEST_ACCOUNTS == "True" ]]; then
@@ -569,13 +557,13 @@
         else
             tempest-account-generator -c $TEMPEST_CONFIG --os-username $ADMIN_USERNAME --os-password $ADMIN_PASSWORD --os-tenant-name $ADMIN_TENANT_NAME -r $TEMPEST_CONCURRENCY etc/accounts.yaml
         fi
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation False
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials False
         iniset $TEMPEST_CONFIG auth test_accounts_file "etc/accounts.yaml"
     elif [[ $TEMPEST_HAS_ADMIN == "False" ]]; then
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-False}
 
     else
-        iniset $TEMPEST_CONFIG auth allow_tenant_isolation ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
+        iniset $TEMPEST_CONFIG auth use_dynamic_credentials ${TEMPEST_ALLOW_TENANT_ISOLATION:-True}
     fi
 
     # Restore IFS
@@ -622,37 +610,8 @@
     popd
 }
 
-# init_tempest() - Initialize EC2 images
-function init_tempest {
-    local base_image_name=cirros-${CIRROS_VERSION}-${CIRROS_ARCH}
-    # /opt/stack/devstack/files/images/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec
-    local image_dir="$FILES/images/${base_image_name}-uec"
-    local kernel="$image_dir/${base_image_name}-vmlinuz"
-    local ramdisk="$image_dir/${base_image_name}-initrd"
-    local disk_image="$image_dir/${base_image_name}-blank.img"
-    if is_service_enabled nova; then
-        # If the CirrOS uec downloaded and the system is UEC capable
-        if [ -f "$kernel" -a -f "$ramdisk" -a -f "$disk_image" -a  "$VIRT_DRIVER" != "openvz" \
-            -a \( "$LIBVIRT_TYPE" != "lxc" -o "$VIRT_DRIVER" != "libvirt" \) ]; then
-            echo "Prepare aki/ari/ami Images"
-            mkdir -p $BOTO_MATERIALS_PATH
-            ( #new namespace
-                # euca2ools should be installed to call euca-* commands
-                is_package_installed euca2ools || install_package euca2ools
-                # tenant:demo ; user: demo
-                source $TOP_DIR/accrc/demo/demo
-                euca-bundle-image -r ${CIRROS_ARCH} -i "$kernel" --kernel true -d "$BOTO_MATERIALS_PATH"
-                euca-bundle-image -r ${CIRROS_ARCH} -i "$ramdisk" --ramdisk true -d "$BOTO_MATERIALS_PATH"
-                euca-bundle-image -r ${CIRROS_ARCH} -i "$disk_image" -d "$BOTO_MATERIALS_PATH"
-            ) 2>&1 </dev/null | cat
-        else
-            echo "Boto materials are not prepared"
-        fi
-    fi
-}
-
 # Restore xtrace
-$XTRACE
+$_XTRACE_TEMPEST
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/lib/template b/lib/template
index 2703788..08d10bb 100644
--- a/lib/template
+++ b/lib/template
@@ -21,7 +21,7 @@
 # - cleanup_XXXX
 
 # Save trace setting
-XTRACE=$(set +o | grep xtrace)
+_XTRACE_TEMPLATE=$(set +o | grep xtrace)
 set +o xtrace
 
 
@@ -92,7 +92,7 @@
 }
 
 # Restore xtrace
-$XTRACE
+$_XTRACE_TEMPLATE
 
 # Tell emacs to use shell-script-mode
 ## Local variables:
diff --git a/pkg/elasticsearch.sh b/pkg/elasticsearch.sh
index 14d13cf..9c4f6f7 100755
--- a/pkg/elasticsearch.sh
+++ b/pkg/elasticsearch.sh
@@ -88,11 +88,7 @@
         sudo dpkg -i ${FILES}/elasticsearch-${ELASTICSEARCH_VERSION}.deb
         sudo update-rc.d elasticsearch defaults 95 10
     elif is_fedora; then
-        if [[ "$os_RELEASE" -ge "21" ]]; then
-            is_package_installed java-1.8.0-openjdk-headless || install_package java-1.8.0-openjdk-headless
-        else
-            is_package_installed java-1.7.0-openjdk-headless || install_package java-1.7.0-openjdk-headless
-        fi
+        is_package_installed java-1.8.0-openjdk-headless || install_package java-1.8.0-openjdk-headless
         yum_install ${FILES}/elasticsearch-${ELASTICSEARCH_VERSION}.noarch.rpm
         sudo /bin/systemctl daemon-reload
         sudo /bin/systemctl enable elasticsearch.service
diff --git a/samples/local.conf b/samples/local.conf
index b92097d..ea68dc0 100644
--- a/samples/local.conf
+++ b/samples/local.conf
@@ -23,10 +23,8 @@
 # While ``stack.sh`` is happy to run without ``localrc``, devlife is better when
 # there are a few minimal variables set:
 
-# If the ``SERVICE_TOKEN`` and ``*_PASSWORD`` variables are not set
-# here you will be prompted to enter values for them by ``stack.sh``
-# and they will be added to ``local.conf``.
-SERVICE_TOKEN=azertytoken
+# If the ``*_PASSWORD`` variables are not set here you will be prompted to enter
+# values for them by ``stack.sh``and they will be added to ``local.conf``.
 ADMIN_PASSWORD=nomoresecrete
 DATABASE_PASSWORD=stackdb
 RABBIT_PASSWORD=stackqueue
@@ -63,7 +61,8 @@
 # Using milestone-proposed branches
 # ---------------------------------
 
-# Uncomment these to grab the milestone-proposed branches from the repos:
+# Uncomment these to grab the milestone-proposed branches from the
+# repos:
 #CINDER_BRANCH=milestone-proposed
 #GLANCE_BRANCH=milestone-proposed
 #HORIZON_BRANCH=milestone-proposed
@@ -74,14 +73,20 @@
 #NEUTRON_BRANCH=milestone-proposed
 #SWIFT_BRANCH=milestone-proposed
 
+# Using git versions of clients
+# -----------------------------
+# By default clients are installed from pip.  See LIBS_FROM_GIT in
+# stackrc for details on getting clients from specific branches or
+# revisions.  e.g.
+# LIBS_FROM_GIT="python-ironicclient"
+# IRONICCLIENT_BRANCH=refs/changes/44/2.../1
 
 # Swift
 # -----
 
-# Swift is now used as the back-end for the S3-like object store. If Nova's
-# objectstore (``n-obj`` in ``ENABLED_SERVICES``) is enabled, it will NOT
-# run if Swift is enabled. Setting the hash value is required and you will
-# be prompted for it if Swift is enabled so just set it to something already:
+# Swift is now used as the back-end for the S3-like object store. Setting the
+# hash value is required and you will be prompted for it if Swift is enabled
+# so just set it to something already:
 SWIFT_HASH=66a3d6b56c1f479c8b4e70ab5c2000f5
 
 # For development purposes the default of 3 replicas is usually not required.
diff --git a/stack.sh b/stack.sh
index 8625b5a..e9831d5 100755
--- a/stack.sh
+++ b/stack.sh
@@ -75,6 +75,7 @@
 
 # Check if run in POSIX shell
 if [[ "${POSIXLY_CORRECT}" == "y" ]]; then
+    set +o xtrace
     echo "You are running POSIX compatibility mode, DevStack requires bash 4.2 or newer."
     exit 1
 fi
@@ -85,11 +86,11 @@
 # action to create a suitable user account.
 
 if [[ $EUID -eq 0 ]]; then
-    echo "You are running this script as root."
-    echo "Cut it out."
-    echo "Really."
-    echo "If you need an account to run DevStack, do this (as root, heh) to create a non-root account:"
-    echo "$TOP_DIR/tools/create-stack-user.sh"
+    set +o xtrace
+    echo "DevStack should be run as a user with sudo permissions, "
+    echo "not root."
+    echo "A \"stack\" user configured correctly can be created with:"
+    echo " $TOP_DIR/tools/create-stack-user.sh"
     exit 1
 fi
 
@@ -98,6 +99,7 @@
 # virtual env, and will fail in really odd ways if you do this. Make
 # this explicit as it has come up on the mailing list.
 if [[ -n "$VIRTUAL_ENV" ]]; then
+    set +o xtrace
     echo "You appear to be running under a python virtualenv."
     echo "DevStack does not support this, as we may break the"
     echo "virtualenv you are currently in by modifying "
@@ -111,6 +113,7 @@
 # on a lot of different environments, you sometimes run it on the
 # wrong box. This makes there be a way to prevent that.
 if [[ -e $HOME/.no-devstack ]]; then
+    set +o xtrace
     echo "You've marked this host as a no-devstack host, to save yourself from"
     echo "running devstack accidentally. If this is in error, please remove the"
     echo "~/.no-devstack file"
@@ -146,19 +149,7 @@
 
 # Phase: local
 rm -f $TOP_DIR/.localrc.auto
-if [[ -r $TOP_DIR/local.conf ]]; then
-    LRC=$(get_meta_section_files $TOP_DIR/local.conf local)
-    for lfile in $LRC; do
-        if [[ "$lfile" == "localrc" ]]; then
-            if [[ -r $TOP_DIR/localrc ]]; then
-                warn $LINENO "localrc and local.conf:[[local]] both exist, using localrc"
-            else
-                echo "# Generated file, do not edit" >$TOP_DIR/.localrc.auto
-                get_meta_section $TOP_DIR/local.conf local $lfile >>$TOP_DIR/.localrc.auto
-            fi
-        fi
-    done
-fi
+extract_localrc_section $TOP_DIR/local.conf $TOP_DIR/localrc $TOP_DIR/.localrc.auto
 
 # ``stack.sh`` is customizable by setting environment variables.  Override a
 # default setting via export::
@@ -192,7 +183,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|vivid|wily|7.0|wheezy|sid|testing|jessie|f21|f22|f23|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (trusty|vivid|wily|7.0|wheezy|sid|testing|jessie|f22|f23|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"
@@ -263,9 +254,7 @@
 # Some distros need to add repos beyond the defaults provided by the vendor
 # to pick up required packages.
 
-if is_fedora && [[ $DISTRO == "rhel7" ]]; then
-    # RHEL requires EPEL for many Open Stack dependencies
-
+function _install_epel_and_rdo {
     # NOTE: We always remove and install latest -- some environments
     # use snapshot images, and if EPEL version updates they break
     # unless we update them to latest version.
@@ -295,18 +284,27 @@
     sudo yum-config-manager --enable epel-bootstrap
     yum_install epel-release || \
         die $LINENO "Error installing EPEL repo, cannot continue"
-    # EPEL rpm has installed it's version
     sudo rm -f /etc/yum.repos.d/epel-bootstrap.repo
 
     # ... and also optional to be enabled
     sudo yum-config-manager --enable rhel-7-server-optional-rpms
 
+    # install the lastest RDO
     sudo yum install -y https://rdoproject.org/repos/rdo-release.rpm
 
     if is_oraclelinux; then
         sudo yum-config-manager --enable ol7_optional_latest ol7_addons ol7_MySQL56
     fi
+}
 
+# If you have all the repos installed above already setup (e.g. a CI
+# situation where they are on your image) you may choose to skip this
+# to speed things up
+SKIP_EPEL_INSTALL=$(trueorfalse False SKIP_EPEL_INSTALL)
+
+if is_fedora && [[ $DISTRO == "rhel7" ]] && \
+        [[ ${SKIP_EPEL_INSTALL} != True ]]; then
+    _install_epel_and_rdo
 fi
 
 
@@ -573,7 +571,8 @@
 
 # Generic helper to configure passwords
 function read_password {
-    XTRACE=$(set +o | grep xtrace)
+    local xtrace
+    xtrace=$(set +o | grep xtrace)
     set +o xtrace
     var=$1; msg=$2
     pw=${!var}
@@ -616,7 +615,9 @@
         eval "$var=$pw"
         echo "$var=$pw" >> $localrc
     fi
-    $XTRACE
+
+    # restore previous xtrace value
+    $xtrace
 }
 
 
@@ -651,9 +652,6 @@
 # --------
 
 if is_service_enabled keystone; then
-    # The ``SERVICE_TOKEN`` is used to bootstrap the Keystone database.  It is
-    # just a string and is not a 'real' Keystone token.
-    read_password SERVICE_TOKEN "ENTER A SERVICE_TOKEN TO USE FOR THE SERVICE ADMIN TOKEN."
     # Services authenticate to Identity with servicename/``SERVICE_PASSWORD``
     read_password SERVICE_PASSWORD "ENTER A SERVICE_PASSWORD TO USE FOR THE SERVICE AUTHENTICATION."
     # Horizon currently truncates usernames and passwords at 20 characters
@@ -837,7 +835,6 @@
     install_django_openstack_auth
     # dashboard
     stack_install_service horizon
-    configure_horizon
 fi
 
 if is_service_enabled heat; then
@@ -994,22 +991,34 @@
     if [ "$KEYSTONE_AUTH_HOST" == "$SERVICE_HOST" ]; then
         init_keystone
         start_keystone
+        bootstrap_keystone
     fi
 
-    export OS_IDENTITY_API_VERSION=3
-
-    # Set up a temporary admin URI for Keystone
-    SERVICE_ENDPOINT=$KEYSTONE_AUTH_URI/v3
-
     if is_service_enabled tls-proxy; then
         export OS_CACERT=$INT_CA_DIR/ca-chain.pem
-        # Until the client support is fixed, just use the internal endpoint
-        SERVICE_ENDPOINT=http://$KEYSTONE_AUTH_HOST:$KEYSTONE_AUTH_PORT_INT/v3
     fi
 
-    # Setup OpenStackClient token-endpoint auth
-    export OS_TOKEN=$SERVICE_TOKEN
-    export OS_URL=$SERVICE_ENDPOINT
+    # Rather than just export these, we write them out to a
+    # intermediate userrc file that can also be used to debug if
+    # something goes wrong between here and running
+    # tools/create_userrc.sh (this script relies on services other
+    # than keystone being available, so we can't call it right now)
+    cat > $TOP_DIR/userrc_early <<EOF
+# Use this for debugging issues before files in accrc are created
+
+# Set up password auth credentials now that Keystone is bootstrapped
+export OS_IDENTITY_API_VERSION=3
+export OS_AUTH_URL=$KEYSTONE_AUTH_URI
+export OS_USERNAME=admin
+export OS_USER_DOMAIN_ID=default
+export OS_PASSWORD=$ADMIN_PASSWORD
+export OS_PROJECT_NAME=admin
+export OS_PROJECT_DOMAIN_ID=default
+export OS_REGION_NAME=$REGION_NAME
+
+EOF
+
+    source $TOP_DIR/userrc_early
 
     create_keystone_accounts
     create_nova_accounts
@@ -1025,30 +1034,6 @@
         create_heat_accounts
     fi
 
-    # Begone token auth
-    unset OS_TOKEN OS_URL
-
-    # Rather than just export these, we write them out to a
-    # intermediate userrc file that can also be used to debug if
-    # something goes wrong between here and running
-    # tools/create_userrc.sh (this script relies on services other
-    # than keystone being available, so we can't call it right now)
-    cat > $TOP_DIR/userrc_early <<EOF
-# Use this for debugging issues before files in accrc are created
-
-# Set up password auth credentials now that Keystone is bootstrapped
-export OS_AUTH_URL=$KEYSTONE_AUTH_URI
-export OS_USERNAME=admin
-export OS_USER_DOMAIN_ID=default
-export OS_PASSWORD=$ADMIN_PASSWORD
-export OS_PROJECT_NAME=admin
-export OS_PROJECT_DOMAIN_ID=default
-export OS_REGION_NAME=$REGION_NAME
-
-EOF
-
-    source $TOP_DIR/userrc_early
-
 fi
 
 # Write a clouds.yaml file
@@ -1057,12 +1042,9 @@
 # Horizon
 # -------
 
-# Set up the django horizon application to serve via apache/wsgi
-
 if is_service_enabled horizon; then
-    echo_summary "Configuring and starting Horizon"
-    init_horizon
-    start_horizon
+    echo_summary "Configuring Horizon"
+    configure_horizon
 fi
 
 
@@ -1287,6 +1269,12 @@
     fi
 fi
 
+if is_service_enabled horizon; then
+    echo_summary "Starting Horizon"
+    init_horizon
+    start_horizon
+fi
+
 
 # Create account rc files
 # =======================
diff --git a/stackrc b/stackrc
index 23a4a7c..16621f1 100644
--- a/stackrc
+++ b/stackrc
@@ -72,18 +72,6 @@
     ENABLED_SERVICES+=,rabbit,tempest,mysql,dstat
 fi
 
-# SQLAlchemy supports multiple database drivers for each database server
-# type. For example, deployer may use MySQLdb, MySQLConnector, or oursql
-# to access MySQL database.
-#
-# When defined, the variable controls which database driver is used to
-# connect to database server. Otherwise using default driver defined for
-# each database type.
-#
-# You can find the list of currently supported drivers for each database
-# type at: http://docs.sqlalchemy.org/en/rel_0_9/core/engines.html
-# SQLALCHEMY_DATABASE_DRIVER="mysqldb"
-
 # Global toggle for enabling services under mod_wsgi. If this is set to
 # ``True`` all services that use HTTPD + mod_wsgi as the preferred method of
 # deployment, will be deployed under Apache. If this is set to ``False`` all
@@ -91,7 +79,7 @@
 ENABLE_HTTPD_MOD_WSGI_SERVICES=True
 
 # Set the default Nova APIs to enable
-NOVA_ENABLED_APIS=ec2,osapi_compute,metadata
+NOVA_ENABLED_APIS=osapi_compute,metadata
 
 # Set the root URL for Horizon
 HORIZON_APACHE_ROOT="/dashboard"
@@ -118,6 +106,17 @@
     source $RC_DIR/.localrc.password
 fi
 
+# Control whether Python 3 should be used.
+export USE_PYTHON3=${USE_PYTHON3:-False}
+
+# 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.
+export PYTHON3_VERSION=${PYTHON3_VERSION:-3.4}
+
+# Just to be more explicit on the Python 2 version to use.
+export PYTHON2_VERSION=${PYTHON2_VERSION:-2.7}
+
 # allow local overrides of env variables, including repo config
 if [[ -f $RC_DIR/localrc ]]; then
     # Old-style user-supplied config
@@ -214,10 +213,6 @@
 HORIZON_REPO=${HORIZON_REPO:-${GIT_BASE}/openstack/horizon.git}
 HORIZON_BRANCH=${HORIZON_BRANCH:-master}
 
-# baremetal provisioning service
-IRONIC_REPO=${IRONIC_REPO:-${GIT_BASE}/openstack/ironic.git}
-IRONIC_BRANCH=${IRONIC_BRANCH:-master}
-
 # unified auth system (manages accounts/tokens)
 KEYSTONE_REPO=${KEYSTONE_REPO:-${GIT_BASE}/openstack/keystone.git}
 KEYSTONE_BRANCH=${KEYSTONE_BRANCH:-master}
@@ -268,6 +263,7 @@
 ##############
 #
 #  OpenStack Client Library Components
+#   Note default install is from pip, see LIBS_FROM_GIT
 #
 ##############
 
@@ -286,6 +282,8 @@
 # ironic client
 GITREPO["python-ironicclient"]=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
 GITBRANCH["python-ironicclient"]=${IRONICCLIENT_BRANCH:-master}
+# ironic plugin is out of tree, but nova uses it. set GITDIR here.
+GITDIR["python-ironicclient"]=$DEST/python-ironicclient
 
 # the base authentication plugins that clients use to authenticate
 GITREPO["keystoneauth"]=${KEYSTONEAUTH_REPO:-${GIT_BASE}/openstack/keystoneauth.git}
@@ -317,6 +315,7 @@
 ###################
 #
 #  Oslo Libraries
+#   Note default install is from pip, see LIBS_FROM_GIT
 #
 ###################
 
@@ -471,6 +470,8 @@
 # ironic common lib
 GITREPO["ironic-lib"]=${IRONIC_LIB_REPO:-${GIT_BASE}/openstack/ironic-lib.git}
 GITBRANCH["ironic-lib"]=${IRONIC_LIB_BRANCH:-master}
+# this doesn't exist in a lib file, so set it here
+GITDIR["ironic-lib"]=$DEST/ironic-lib
 
 
 ##################
@@ -671,6 +672,9 @@
 # Service startup timeout
 SERVICE_TIMEOUT=${SERVICE_TIMEOUT:-60}
 
+# Service graceful shutdown timeout
+SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT=${SERVICE_GRACEFUL_SHUTDOWN_TIMEOUT:-5}
+
 # Support alternative yum -- in future Fedora 'dnf' will become the
 # only supported installer, but for now 'yum' and 'dnf' are both
 # available in parallel with compatible CLIs.  Allow manual switching
diff --git a/tests/run-process.sh b/tests/run-process.sh
index bdf1395..301b9a0 100755
--- a/tests/run-process.sh
+++ b/tests/run-process.sh
@@ -5,7 +5,7 @@
 #
 # Set USE_SCREEN True|False to change use of screen.
 #
-# This script emulates the basic exec envirnment in ``stack.sh`` to test
+# This script emulates the basic exec environment in ``stack.sh`` to test
 # the process spawn and kill operations.
 
 if [[ -z $1 ]]; then
diff --git a/tests/test_ini_config.sh b/tests/test_ini_config.sh
index d9cb8d8..a5e1107 100755
--- a/tests/test_ini_config.sh
+++ b/tests/test_ini_config.sh
@@ -80,6 +80,11 @@
     sudo chown -R root:root ${INI_TMP_ETC_DIR}
 fi
 
+# test iniget_sections
+VAL=$(iniget_sections "${TEST_INI}")
+assert_equal "$VAL" "default aaa bbb ccc ddd eee del_separate_options \
+del_same_option del_missing_option del_missing_option_multi del_no_options"
+
 # Test with missing arguments
 BEFORE=$(cat ${TEST_INI})
 
diff --git a/tests/test_package_ordering.sh b/tests/test_package_ordering.sh
new file mode 100755
index 0000000..a568abf
--- /dev/null
+++ b/tests/test_package_ordering.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# basic test to ensure that package-install files remain sorted
+# alphabetically.
+
+TOP=$(cd $(dirname "$0")/.. && pwd)
+
+source $TOP/tests/unittest.sh
+
+PKG_FILES=$(find $TOP/files/debs $TOP/files/rpms $TOP/files/rpms-suse -type f)
+
+TMPDIR=$(mktemp -d)
+
+SORTED=${TMPDIR}/sorted
+UNSORTED=${TMPDIR}/unsorted
+
+for p in $PKG_FILES; do
+    grep -v '^#' $p > ${UNSORTED}
+    sort ${UNSORTED} > ${SORTED}
+
+    if [ -n "$(diff -c ${UNSORTED} ${SORTED})" ]; then
+        failed "$p is unsorted"
+        # output this, it's helpful to see what exactly is unsorted
+        diff -c ${UNSORTED} ${SORTED}
+    else
+        passed "$p is sorted"
+    fi
+done
+
+rm -rf ${TMPDIR}
+
+report_results
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index 25f713c..93d5d69 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -156,7 +156,7 @@
     exit 3
 fi
 
-export -n SERVICE_TOKEN SERVICE_ENDPOINT OS_SERVICE_TOKEN OS_SERVICE_ENDPOINT
+export -n SERVICE_ENDPOINT OS_SERVICE_ENDPOINT
 
 EC2_URL=$(openstack endpoint list --service ec2 --interface public --os-identity-api-version=3 -c URL -f value || true)
 if [[ -z $EC2_URL ]]; then
diff --git a/tools/dstat.sh b/tools/dstat.sh
index 6ba4515..3c0b3be 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"
+DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv --swap"
 
 # Command-line arguments for secondary background DStat process.
 DSTAT_CSV_OPTS="-tcmndrylpg --output $LOGDIR/dstat-csv.log"
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 9ae2ae7..193a1f7 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -135,7 +135,7 @@
         fi
     fi
 
-    if  [[ "$os_VENDOR" == "Fedora" ]] && [[ "$os_RELEASE" -ge "21" ]]; then
+    if  [[ "$os_VENDOR" == "Fedora" ]] && [[ "$os_RELEASE" -ge "22" ]]; then
         # requests ships vendored version of chardet/urllib3, but on
         # fedora these are symlinked back to the primary versions to
         # avoid duplication of code on disk.  This is fine when
diff --git a/tools/image_list.sh b/tools/image_list.sh
index a27635e..27b3d46 100755
--- a/tools/image_list.sh
+++ b/tools/image_list.sh
@@ -3,6 +3,12 @@
 # Keep track of the DevStack directory
 TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
 
+# The following "source" implicitly calls get_default_host_ip() in
+# stackrc and will die if the selected default IP happens to lie
+# in the default ranges for FIXED_RANGE or FLOATING_RANGE. Since we
+# do not really need HOST_IP to be properly set in the remainder of
+# this script, just set it to some dummy value and make stackrc happy.
+HOST_IP=SKIP
 source $TOP_DIR/functions
 
 # Possible virt drivers, if we have more, add them here. Always keep
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index ab5efb2..f239c7b 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -8,6 +8,7 @@
 
 # Assumptions:
 # - update pip to $INSTALL_PIP_VERSION
+# - if USE_PYTHON3=True, PYTHON3_VERSION refers to a version already installed
 
 set -o errexit
 set -o xtrace
@@ -31,6 +32,8 @@
 echo "Distro: $DISTRO"
 
 function get_versions {
+    # FIXME(dhellmann): Deal with multiple python versions here? This
+    # is just used for reporting, so maybe not?
     PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null || true)
     if [[ -n $PIP ]]; then
         PIP_VERSION=$($PIP --version | awk '{ print $2}')
@@ -75,6 +78,9 @@
         touch $LOCAL_PIP.downloaded
     fi
     sudo -H -E python $LOCAL_PIP
+    if python3_enabled; then
+        sudo -H -E python${PYTHON3_VERSION} $LOCAL_PIP
+    fi
 }
 
 
@@ -114,6 +120,7 @@
 # python in f23 depends on the python-pip package
 if ! { is_fedora && [[ $DISTRO == "f23" ]]; }; then
     uninstall_package python-pip
+    uninstall_package python3-pip
 fi
 
 install_get_pip
@@ -122,6 +129,7 @@
     configure_pypi_alternative_url
 fi
 
+set -x
 pip_install -U setuptools
 
 get_versions
diff --git a/tools/install_prereqs.sh b/tools/install_prereqs.sh
index 38452cd..031f8a8 100755
--- a/tools/install_prereqs.sh
+++ b/tools/install_prereqs.sh
@@ -81,6 +81,9 @@
     fi
 fi
 
+if python3_enabled; then
+    install_python3
+fi
 
 # Mark end of run
 # ---------------
diff --git a/tools/ironic/scripts/cleanup-node b/tools/ironic/scripts/cleanup-node
deleted file mode 100755
index c4e4e70..0000000
--- a/tools/ironic/scripts/cleanup-node
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-# **cleanup-nodes**
-
-# Cleans up baremetal poseur nodes and volumes created during ironic setup
-# Assumes calling user has proper libvirt group membership and access.
-
-set -exu
-
-LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-NAME=$1
-NETWORK_BRIDGE=$2
-
-export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
-
-VOL_NAME="$NAME.qcow2"
-virsh list | grep -q $NAME && virsh destroy $NAME
-virsh list --inactive | grep -q $NAME && virsh undefine $NAME
-
-if virsh pool-list | grep -q $LIBVIRT_STORAGE_POOL ; then
-  virsh vol-list $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
-      virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL
-fi
diff --git a/tools/ironic/scripts/configure-vm b/tools/ironic/scripts/configure-vm
deleted file mode 100755
index 378fcb8..0000000
--- a/tools/ironic/scripts/configure-vm
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-
-import argparse
-import os.path
-
-import libvirt
-
-templatedir = os.path.join(os.path.dirname(os.path.dirname(__file__)),
-                           'templates')
-
-
-CONSOLE_LOG = """
-    <serial type='file'>
-      <source path='%(console_log)s'/>
-      <target port='0'/>
-      <alias name='serial0'/>
-    </serial>
-    <serial type='pty'>
-      <source path='/dev/pts/49'/>
-      <target port='1'/>
-      <alias name='serial1'/>
-    </serial>
-    <console type='file'>
-      <source path='%(console_log)s'/>
-      <target type='serial' port='0'/>
-      <alias name='serial0'/>
-    </console>
-"""
-
-
-def main():
-    parser = argparse.ArgumentParser(
-        description="Configure a kvm virtual machine for the seed image.")
-    parser.add_argument('--name', default='seed',
-                        help='the name to give the machine in libvirt.')
-    parser.add_argument('--image',
-                        help='Use a custom image file (must be qcow2).')
-    parser.add_argument('--engine', default='qemu',
-                        help='The virtualization engine to use')
-    parser.add_argument('--arch', default='i686',
-                        help='The architecture to use')
-    parser.add_argument('--memory', default='2097152',
-                        help="Maximum memory for the VM in KB.")
-    parser.add_argument('--cpus', default='1',
-                        help="CPU count for the VM.")
-    parser.add_argument('--bootdev', default='hd',
-                        help="What boot device to use (hd/network).")
-    parser.add_argument('--network', default="brbm",
-                        help='The libvirt network name to use')
-    parser.add_argument('--libvirt-nic-driver', default='e1000',
-                        help='The libvirt network driver to use')
-    parser.add_argument('--console-log',
-                        help='File to log console')
-    parser.add_argument('--emulator', default=None,
-                        help='Path to emulator bin for vm template')
-    args = parser.parse_args()
-    with file(templatedir + '/vm.xml', 'rb') as f:
-        source_template = f.read()
-    params = {
-        'name': args.name,
-        'imagefile': args.image,
-        'engine': args.engine,
-        'arch': args.arch,
-        'memory': args.memory,
-        'cpus': args.cpus,
-        'bootdev': args.bootdev,
-        'network': args.network,
-        'nicdriver': args.libvirt_nic_driver,
-        'emulator': args.emulator,
-    }
-
-    if args.emulator:
-        params['emulator'] = args.emulator
-    else:
-        if os.path.exists("/usr/bin/kvm"):  # Debian
-            params['emulator'] = "/usr/bin/kvm"
-        elif os.path.exists("/usr/bin/qemu-kvm"):  # Redhat
-            params['emulator'] = "/usr/bin/qemu-kvm"
-
-    if args.console_log:
-        params['bios_serial'] = "<bios useserial='yes'/>"
-        params['console_log'] = CONSOLE_LOG % {'console_log': args.console_log}
-    else:
-        params['bios_serial'] = ''
-        params['console_log'] = ''
-    libvirt_template = source_template % params
-    conn = libvirt.open("qemu:///system")
-
-    a = conn.defineXML(libvirt_template)
-    print ("Created machine %s with UUID %s" % (args.name, a.UUIDString()))
-
-if __name__ == '__main__':
-    main()
diff --git a/tools/ironic/scripts/create-node b/tools/ironic/scripts/create-node
deleted file mode 100755
index b018acd..0000000
--- a/tools/ironic/scripts/create-node
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/env bash
-
-# **create-nodes**
-
-# Creates baremetal poseur nodes for ironic testing purposes
-
-set -ex
-
-# Keep track of the DevStack directory
-TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
-
-NAME=$1
-CPU=$2
-MEM=$(( 1024 * $3 ))
-# Extra G to allow fuzz for partition table : flavor size and registered size
-# need to be different to actual size.
-DISK=$(( $4 + 1))
-
-case $5 in
-    i386) ARCH='i686' ;;
-    amd64) ARCH='x86_64' ;;
-    *) echo "Unsupported arch $4!" ; exit 1 ;;
-esac
-
-BRIDGE=$6
-EMULATOR=$7
-LOGDIR=$8
-
-LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"}
-LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"}
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-export VIRSH_DEFAULT_CONNECT_URI=$LIBVIRT_CONNECT_URI
-
-if ! virsh pool-list --all | grep -q $LIBVIRT_STORAGE_POOL; then
-    virsh pool-define-as --name $LIBVIRT_STORAGE_POOL dir --target /var/lib/libvirt/images >&2
-    virsh pool-autostart $LIBVIRT_STORAGE_POOL >&2
-    virsh pool-start $LIBVIRT_STORAGE_POOL >&2
-fi
-
-pool_state=$(virsh pool-info $LIBVIRT_STORAGE_POOL | grep State | awk '{ print $2 }')
-if [ "$pool_state" != "running" ] ; then
-  [ ! -d /var/lib/libvirt/images ] && sudo mkdir /var/lib/libvirt/images
-  virsh pool-start $LIBVIRT_STORAGE_POOL >&2
-fi
-
-if [ -n "$LOGDIR" ] ; then
-  mkdir -p "$LOGDIR"
-fi
-
-PREALLOC=
-if [ -f /etc/debian_version ]; then
-    PREALLOC="--prealloc-metadata"
-fi
-
-if [ -n "$LOGDIR" ] ; then
-  VM_LOGGING="--console-log $LOGDIR/${NAME}_console.log"
-else
-  VM_LOGGING=""
-fi
-VOL_NAME="${NAME}.qcow2"
-
-if ! virsh list --all | grep -q $NAME; then
-  virsh vol-list --pool $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME &&
-      virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL >&2
-  virsh vol-create-as $LIBVIRT_STORAGE_POOL ${VOL_NAME} ${DISK}G --format qcow2 $PREALLOC >&2
-  volume_path=$(virsh vol-path --pool $LIBVIRT_STORAGE_POOL $VOL_NAME)
-  # Pre-touch the VM to set +C, as it can only be set on empty files.
-  sudo touch "$volume_path"
-  sudo chattr +C "$volume_path" || true
-  $TOP_DIR/scripts/configure-vm \
-    --bootdev network --name $NAME --image "$volume_path" \
-    --arch $ARCH --cpus $CPU --memory $MEM --libvirt-nic-driver $LIBVIRT_NIC_DRIVER \
-    --emulator $EMULATOR --network $BRIDGE $VM_LOGGING >&2
-
-fi
-
-# echo mac
-virsh dumpxml $NAME | grep "mac address" | head -1 | cut -d\' -f2
diff --git a/tools/ironic/scripts/setup-network b/tools/ironic/scripts/setup-network
deleted file mode 100755
index 83308ed..0000000
--- a/tools/ironic/scripts/setup-network
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-
-# **setup-network**
-
-# Setups openvswitch libvirt network suitable for
-# running baremetal poseur nodes for ironic testing purposes
-
-set -exu
-
-LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"}
-
-# Keep track of the DevStack directory
-TOP_DIR=$(cd $(dirname "$0")/.. && pwd)
-BRIDGE_SUFFIX=${1:-''}
-BRIDGE_NAME=brbm$BRIDGE_SUFFIX
-
-export VIRSH_DEFAULT_CONNECT_URI="$LIBVIRT_CONNECT_URI"
-
-# Only add bridge if missing
-(sudo ovs-vsctl list-br | grep ${BRIDGE_NAME}$) || sudo ovs-vsctl add-br ${BRIDGE_NAME}
-
-# Remove bridge before replacing it.
-(virsh net-list | grep "${BRIDGE_NAME} ") && virsh net-destroy ${BRIDGE_NAME}
-(virsh net-list --inactive  | grep "${BRIDGE_NAME} ") && virsh net-undefine ${BRIDGE_NAME}
-
-virsh net-define <(sed s/brbm/$BRIDGE_NAME/ $TOP_DIR/templates/brbm.xml)
-virsh net-autostart ${BRIDGE_NAME}
-virsh net-start ${BRIDGE_NAME}
diff --git a/tools/ironic/templates/brbm.xml b/tools/ironic/templates/brbm.xml
deleted file mode 100644
index 0769d3f..0000000
--- a/tools/ironic/templates/brbm.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<network>
-  <name>brbm</name>
-  <forward mode='bridge'/>
-  <bridge name='brbm'/>
-  <virtualport type='openvswitch'/>
-</network>
diff --git a/tools/ironic/templates/tftpd-xinetd.template b/tools/ironic/templates/tftpd-xinetd.template
deleted file mode 100644
index 5f3d03f..0000000
--- a/tools/ironic/templates/tftpd-xinetd.template
+++ /dev/null
@@ -1,14 +0,0 @@
-service tftp
-{
-  protocol        = udp
-  port            = 69
-  socket_type     = dgram
-  wait            = yes
-  user            = root
-  server          = /usr/sbin/in.tftpd
-  server_args     = -v -v -v -v -v --map-file %TFTPBOOT_DIR%/map-file %TFTPBOOT_DIR%
-  disable         = no
-  # This is a workaround for Fedora, where TFTP will listen only on
-  # IPv6 endpoint, if IPv4 flag is not used.
-  flags           = IPv4
-}
diff --git a/tools/ironic/templates/vm.xml b/tools/ironic/templates/vm.xml
deleted file mode 100644
index ae7d685..0000000
--- a/tools/ironic/templates/vm.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<domain type='%(engine)s'>
-  <name>%(name)s</name>
-  <memory unit='KiB'>%(memory)s</memory>
-  <vcpu>%(cpus)s</vcpu>
-  <os>
-    <type arch='%(arch)s' machine='pc-1.0'>hvm</type>
-    <boot dev='%(bootdev)s'/>
-    <bootmenu enable='no'/>
-    %(bios_serial)s
-  </os>
-  <features>
-    <acpi/>
-    <apic/>
-    <pae/>
-  </features>
-  <clock offset='utc'/>
-  <on_poweroff>destroy</on_poweroff>
-  <on_reboot>restart</on_reboot>
-  <on_crash>restart</on_crash>
-  <devices>
-    <emulator>%(emulator)s</emulator>
-    <disk type='file' device='disk'>
-      <driver name='qemu' type='qcow2' cache='writeback'/>
-      <source file='%(imagefile)s'/>
-      <target dev='vda' bus='virtio'/>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
-    </disk>
-    <controller type='ide' index='0'>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
-    </controller>
-    <interface type='network'>
-      <source network='%(network)s'/>
-      <virtualport type='openvswitch'/>
-      <model type='%(nicdriver)s'/>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
-    </interface>
-    <input type='mouse' bus='ps2'/>
-    <graphics type='vnc' port='-1' autoport='yes'/>
-    <video>
-      <model type='cirrus' vram='9216' heads='1'/>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
-    </video>
-    %(console_log)s
-    <memballoon model='virtio'>
-      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
-    </memballoon>
-  </devices>
-</domain>
-
diff --git a/tools/update_clouds_yaml.py b/tools/update_clouds_yaml.py
index 3a364fe..eb7265f 100755
--- a/tools/update_clouds_yaml.py
+++ b/tools/update_clouds_yaml.py
@@ -36,6 +36,7 @@
         self._cloud_data = {
             'region_name': args.os_region_name,
             'identity_api_version': args.os_identity_api_version,
+            'volume_api_version': args.os_volume_api_version,
             'auth': {
                 'auth_url': args.os_auth_url,
                 'username': args.os_username,
@@ -82,6 +83,7 @@
     parser.add_argument('--os-cloud', required=True)
     parser.add_argument('--os-region-name', default='RegionOne')
     parser.add_argument('--os-identity-api-version', default='3')
+    parser.add_argument('--os-volume-api-version', default='2')
     parser.add_argument('--os-cacert')
     parser.add_argument('--os-auth-url', required=True)
     parser.add_argument('--os-username', required=True)
diff --git a/tools/xen/README.md b/tools/xen/README.md
index a1adf59..21090e5 100644
--- a/tools/xen/README.md
+++ b/tools/xen/README.md
@@ -78,7 +78,6 @@
     # to prompt for these passwords, blocking the install process.
 
     DATABASE_PASSWORD=my_super_secret
-    SERVICE_TOKEN=my_super_secret
     ADMIN_PASSWORD=my_super_secret
     SERVICE_PASSWORD=my_super_secret
     RABBIT_PASSWORD=my_super_secret
diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh
index e24d9ed..46ff0b6 100755
--- a/tools/xen/install_os_domU.sh
+++ b/tools/xen/install_os_domU.sh
@@ -12,13 +12,6 @@
 
 export LC_ALL=C
 
-# Abort if localrc is not set
-if [ ! -e ../../localrc ]; then
-    echo "You must have a localrc with ALL necessary passwords defined before proceeding."
-    echo "See the xen README for required passwords."
-    exit 1
-fi
-
 # This directory
 THIS_DIR=$(cd $(dirname "$0") && pwd)
 
@@ -31,6 +24,10 @@
 #
 # Get Settings
 #
+TOP_DIR=$(cd $THIS_DIR/../../ && pwd)
+source $TOP_DIR/inc/meta-config
+rm -f $TOP_DIR/.localrc.auto
+extract_localrc_section $TOP_DIR/local.conf $TOP_DIR/localrc $TOP_DIR/.localrc.auto
 
 # Source params - override xenrc params in your localrc to suit your taste
 source $THIS_DIR/xenrc
diff --git a/tox.ini b/tox.ini
index 9279455..f9d04f2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -12,20 +12,20 @@
    {env:BASHATE_INSTALL_PATH:bashate==0.3.2}
 whitelist_externals = bash
 commands = bash -c "find {toxinidir}             \
-         -not \( -type d -name .?\* -prune \)    \ # prune all 'dot' dirs
-         -not \( -type d -name doc -prune \)     \ # skip documentation
-         -not \( -type d -name shocco -prune \)  \ # skip shocco
-         -type f                                 \ # only files
-         -not -name \*~                          \ # skip editors, readme, etc
+         -not \( -type d -name .?\* -prune \)    \
+         -not \( -type d -name doc -prune \)     \
+         -not \( -type d -name shocco -prune \)  \
+         -type f                                 \
+         -not -name \*~                          \
          -not -name \*.md                        \
          \(                                      \
           -name \*.sh -or                        \
           -name \*.orig -or                      \
-          -name \*rc -or                         \ # openrc files, etc
+          -name \*rc -or                         \
           -name functions\* -or                  \
-          -wholename \*/inc/\* -or               \ # /inc files and
-          -wholename \*/lib/\*                   \ # /lib files are shell, but
-         \)                                      \ #   have no extension
+          -wholename \*/inc/\* -or               \
+          -wholename \*/lib/\*                   \
+         \)                                      \
          -print0 | xargs -0 bashate -v -iE006 -eE005,E042"
 
 [testenv:docs]