Merge "Cleanup nova v2.1 API testing options"
diff --git a/README.md b/README.md
index ee7f0e7..dd394c2 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
 * To provide an environment for the OpenStack CI testing on every commit
   to the projects
 
-Read more at http://devstack.org.
+Read more at http://docs.openstack.org/developer/devstack
 
 IMPORTANT: Be sure to carefully read `stack.sh` and any other scripts you
 execute before you run them, as they install software and will alter your
@@ -94,4 +94,4 @@
 `local.conf`.  It is likely that you will need to provide and modify
 this file if you want anything other than the most basic setup.  Start
 by reading the [configuration guide](doc/source/configuration.rst) for
-details of the configuration file and the many available options.
\ No newline at end of file
+details of the configuration file and the many available options.
diff --git a/clean.sh b/clean.sh
index 74bcaee..b22a29c 100755
--- a/clean.sh
+++ b/clean.sh
@@ -41,13 +41,13 @@
 source $TOP_DIR/lib/tls
 
 source $TOP_DIR/lib/oslo
+source $TOP_DIR/lib/lvm
 source $TOP_DIR/lib/horizon
 source $TOP_DIR/lib/keystone
 source $TOP_DIR/lib/glance
 source $TOP_DIR/lib/nova
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
-source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ironic
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index fe23d6c..7ca82c7 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -18,11 +18,12 @@
 
 The new header is similar to a normal INI section header but with double
 brackets (``[[ ... ]]``) and two internal fields separated by a pipe
-(``|``):
-
+(``|``). Note that there are no spaces between the double brackets and the
+internal fields. Likewise, there are no spaces between the pipe and the
+internal fields:
 ::
 
-    [[ <phase> | <config-file-name> ]]
+    '[[' <phase> '|' <config-file-name> ']]'
 
 where ``<phase>`` is one of a set of phase names defined by ``stack.sh``
 and ``<config-file-name>`` is the configuration filename. The filename
@@ -297,6 +298,12 @@
     SWIFT_USE_MOD_WSGI="True"
 
 
+Example (Cinder):
+
+::
+
+    CINDER_USE_MOD_WSGI="True"
+
 
 Libraries from Git
 ------------------
@@ -383,6 +390,24 @@
 ``files/keystone_data.sh``
 
 
+Guest Images
+------------
+
+Images provided in URLS via the comma-separated ``IMAGE_URLS``
+variable will be downloaded and uploaded to glance by DevStack.
+
+Default guest-images are predefined for each type of hypervisor and
+their testing-requirements in ``stack.sh``.  Setting
+``DOWNLOAD_DEFAULT_IMAGES=False`` will prevent DevStack downloading
+these default images; in that case, you will want to populate
+``IMAGE_URLS`` with sufficient images to satisfy testing-requirements.
+
+    ::
+
+        DOWNLOAD_DEFAULT_IMAGES=False
+        IMAGE_URLS="http://foo.bar.com/image.qcow,"
+        IMAGE_URLS+="http://foo.bar.com/image2.qcow"
+
 IP Version
 ----------
 
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 40a5632..2973eb6 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -59,7 +59,7 @@
 
         ## Neutron options
         Q_USE_SECGROUP=True
-        FLOATING_RANGE="172.18.161.1/24"
+        FLOATING_RANGE="172.18.161.0/24"
         FIXED_RANGE="10.0.0.0/24"
         Q_FLOATING_ALLOCATION_POOL=start=172.18.161.250,end=172.18.161.254
         PUBLIC_NETWORK_GATEWAY="172.18.161.1"
diff --git a/doc/source/guides/single-vm.rst b/doc/source/guides/single-vm.rst
index c2ce1a3..515cd50 100644
--- a/doc/source/guides/single-vm.rst
+++ b/doc/source/guides/single-vm.rst
@@ -78,6 +78,11 @@
 As DevStack will refuse to run as root, this configures ``cloud-init``
 to create a non-root user and run the ``start.sh`` script as that user.
 
+If you are using cloud-init and you have not
+`enabled custom logging <../configuration.html#enable-logging>`_ of the stack
+output, then the stack output can be found in
+``/var/log/cloud-init-output.log`` by default.
+
 Launching By Hand
 -----------------
 
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 2dd0241..99e96b1 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -154,7 +154,6 @@
 * `functions <functions.html>`__ - DevStack-specific functions
 * `functions-common <functions-common.html>`__ - Functions shared with other projects
 * `lib/apache <lib/apache.html>`__
-* `lib/ceilometer <lib/ceilometer.html>`__
 * `lib/ceph <lib/ceph.html>`__
 * `lib/cinder <lib/cinder.html>`__
 * `lib/database <lib/database.html>`__
@@ -173,7 +172,7 @@
 * `lib/swift <lib/swift.html>`__
 * `lib/tempest <lib/tempest.html>`__
 * `lib/tls <lib/tls.html>`__
-* `lib/zaqar <lib/zaqar.html>`__
+* `lib/trove <lib/trove.html>`__
 * `unstack.sh <unstack.sh.html>`__
 * `clean.sh <clean.sh.html>`__
 * `run\_tests.sh <run_tests.sh.html>`__
@@ -181,7 +180,6 @@
 * `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/70-zaqar.sh <extras.d/70-zaqar.sh.html>`__
 * `extras.d/80-tempest.sh <extras.d/80-tempest.sh.html>`__
 
 * `inc/ini-config <inc/ini-config.html>`__
@@ -239,4 +237,3 @@
 * `exercises/sec\_groups.sh <exercises/sec_groups.sh.html>`__
 * `exercises/swift.sh <exercises/swift.sh.html>`__
 * `exercises/volumes.sh <exercises/volumes.sh.html>`__
-* `exercises/zaqar.sh <exercises/zaqar.sh.html>`__
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 99bfb85..85fd7cc 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -17,17 +17,29 @@
 
 The following are plugins that exist for official OpenStack projects.
 
-+--------------------+-------------------------------------------+--------------------+
-|Plugin Name         |URL                                        |Comments            |
-+--------------------+-------------------------------------------+--------------------+
-|magnum              |git://git.openstack.org/openstack/magnum   |                    |
-+--------------------+-------------------------------------------+--------------------+
-|sahara              |git://git.openstack.org/openstack/sahara   |                    |
-+--------------------+-------------------------------------------+--------------------+
-|trove               |git://git.openstack.org/openstack/trove    |                    |
-+--------------------+-------------------------------------------+--------------------+
-|zaqar               |git://git.openstack.org/openstack/zaqar    |                    |
-+--------------------+-------------------------------------------+--------------------+
++------------------+---------------------------------------------+--------------------+
+|Plugin Name       |URL                                          |Comments            |
++------------------+---------------------------------------------+--------------------+
+|aodh              |git://git.openstack.org/openstack/aodh       | alarming           |
++------------------+---------------------------------------------+--------------------+
+|ceilometer        |git://git.openstack.org/openstack/ceilometer | metering           |
++------------------+---------------------------------------------+--------------------+
+|gnocchi           |git://git.openstack.org/openstack/gnocchi    | metric             |
++------------------+---------------------------------------------+--------------------+
+|magnum            |git://git.openstack.org/openstack/magnum     |                    |
++------------------+---------------------------------------------+--------------------+
+|manila            |git://git.openstack.org/openstack/manila     | file shares        |
++------------------+---------------------------------------------+--------------------+
+|mistral           |git://git.openstack.org/openstack/mistral    |                    |
++------------------+---------------------------------------------+--------------------+
+|rally             |git://git.openstack.org/openstack/rally      |                    |
++------------------+---------------------------------------------+--------------------+
+|sahara            |git://git.openstack.org/openstack/sahara     |                    |
++------------------+---------------------------------------------+--------------------+
+|trove             |git://git.openstack.org/openstack/trove      |                    |
++------------------+---------------------------------------------+--------------------+
+|zaqar             |git://git.openstack.org/openstack/zaqar      |                    |
++------------------+---------------------------------------------+--------------------+
 
 
 
@@ -62,14 +74,16 @@
 Additional Services
 ===================
 
-+-------------+------------------------------------------+------------+
-| Plugin Name | URL                                      | Comments   |
-|             |                                          |            |
-+-------------+------------------------------------------+------------+
-|ec2-api      |git://git.openstack.org/stackforge/ec2api |[as1]_      |
-+-------------+------------------------------------------+------------+
-|             |                                          |            |
-+-------------+------------------------------------------+------------+
++----------------+--------------------------------------------------+------------+
+| Plugin Name    | URL                                              | Comments   |
+|                |                                                  |            |
++----------------+--------------------------------------------------+------------+
+|ec2-api         |git://git.openstack.org/stackforge/ec2api         |[as1]_      |
++----------------+--------------------------------------------------+------------+
+|ironic-inspector|git://git.openstack.org/openstack/ironic-inspector|            |
++----------------+--------------------------------------------------+------------+
+|                |                                                  |            |
++----------------+--------------------------------------------------+------------+
 
 .. [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 803dd08..fda601b 100644
--- a/doc/source/plugins.rst
+++ b/doc/source/plugins.rst
@@ -178,7 +178,7 @@
 ===============
 
 Devstack provides a framework for getting packages installed at an early
-phase of its execution. This packages may be defined in a plugin as files
+phase of its execution. These packages may be defined in a plugin as files
 that contain new-line separated lists of packages required by the plugin
 
 Supported packaging systems include apt and yum across multiple distributions.
diff --git a/exercises/zaqar.sh b/exercises/zaqar.sh
deleted file mode 100755
index c370b12..0000000
--- a/exercises/zaqar.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-
-# **zaqar.sh**
-
-# Sanity check that Zaqar started if enabled
-
-echo "*********************************************************************"
-echo "Begin DevStack Exercise: $0"
-echo "*********************************************************************"
-
-# This script exits on an error so that errors don't compound and you see
-# only the first error that occurred.
-set -o errexit
-
-# Print the commands being run so that we can see the command that triggers
-# an error.  It is also useful for following allowing as the install occurs.
-set -o xtrace
-
-
-# Settings
-# ========
-
-# Keep track of the current directory
-EXERCISE_DIR=$(cd $(dirname "$0") && pwd)
-TOP_DIR=$(cd $EXERCISE_DIR/..; pwd)
-
-# Import common functions
-source $TOP_DIR/functions
-
-# Import configuration
-source $TOP_DIR/openrc
-
-# Import exercise configuration
-source $TOP_DIR/exerciserc
-
-is_service_enabled zaqar-server || exit 55
-
-$CURL_GET http://$SERVICE_HOST:8888/v1/ 2>/dev/null | grep -q 'queue_name' || die $LINENO "Zaqar API not functioning!"
-
-set +o xtrace
-echo "*********************************************************************"
-echo "SUCCESS: End DevStack Exercise: $0"
-echo "*********************************************************************"
diff --git a/extras.d/70-zaqar.sh b/extras.d/70-zaqar.sh
deleted file mode 100644
index 63c4fd5..0000000
--- a/extras.d/70-zaqar.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-# zaqar.sh - Devstack extras script to install Zaqar
-
-if is_service_enabled zaqar-server; then
-    if [[ "$1" == "source" ]]; then
-        # Initial source
-        source $TOP_DIR/lib/zaqar
-    elif [[ "$1" == "stack" && "$2" == "install" ]]; then
-        echo_summary "Installing Zaqar"
-        install_zaqarclient
-        install_zaqar
-    elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
-        echo_summary "Configuring Zaqar"
-        configure_zaqar
-        configure_zaqarclient
-
-        if is_service_enabled key; then
-            create_zaqar_accounts
-        fi
-
-    elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
-        echo_summary "Initializing Zaqar"
-        init_zaqar
-        start_zaqar
-    fi
-
-    if [[ "$1" == "unstack" ]]; then
-        stop_zaqar
-    fi
-fi
diff --git a/files/apache-ceilometer.template b/files/apache-ceilometer.template
deleted file mode 100644
index 79f14c3..0000000
--- a/files/apache-ceilometer.template
+++ /dev/null
@@ -1,15 +0,0 @@
-Listen %PORT%
-
-<VirtualHost *:%PORT%>
-    WSGIDaemonProcess ceilometer-api processes=2 threads=10 user=%USER% display-name=%{GROUP} %VIRTUALENV%
-    WSGIProcessGroup ceilometer-api
-    WSGIScriptAlias / %WSGIAPP%
-    WSGIApplicationGroup %{GLOBAL}
-    <IfVersion >= 2.4>
-        ErrorLogFormat "%{cu}t %M"
-    </IfVersion>
-    ErrorLog /var/log/%APACHE_NAME%/ceilometer.log
-    CustomLog /var/log/%APACHE_NAME%/ceilometer_access.log combined
-</VirtualHost>
-
-WSGISocketPrefix /var/run/%APACHE_NAME%
diff --git a/files/apache-cinder-api.template b/files/apache-cinder-api.template
new file mode 100644
index 0000000..e1246f1
--- /dev/null
+++ b/files/apache-cinder-api.template
@@ -0,0 +1,26 @@
+Listen %PUBLICPORT%
+
+<VirtualHost *:%PUBLICPORT%>
+    WSGIDaemonProcess osapi_volume processes=%APIWORKERS% threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
+    WSGIProcessGroup osapi_volume
+    WSGIScriptAlias / %CINDER_BIN_DIR%/cinder-wsgi
+    WSGIApplicationGroup %{GLOBAL}
+    WSGIPassAuthorization On
+    <IfVersion >= 2.4>
+      ErrorLogFormat "%{cu}t %M"
+    </IfVersion>
+    ErrorLog /var/log/%APACHE_NAME%/c-api.log
+    %SSLENGINE%
+    %SSLCERTFILE%
+    %SSLKEYFILE%
+
+    <Directory %CINDER_BIN_DIR%>
+        <IfVersion >= 2.4>
+            Require all granted
+        </IfVersion>
+        <IfVersion < 2.4>
+            Order allow,deny
+            Allow from all
+        </IfVersion>
+    </Directory>
+</VirtualHost>
diff --git a/files/apache-keystone.template b/files/apache-keystone.template
index 6dd1ad9..4d3d2d6 100644
--- a/files/apache-keystone.template
+++ b/files/apache-keystone.template
@@ -5,7 +5,7 @@
 <VirtualHost *:%PUBLICPORT%>
     WSGIDaemonProcess keystone-public processes=5 threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
     WSGIProcessGroup keystone-public
-    WSGIScriptAlias / %PUBLICWSGI%
+    WSGIScriptAlias / %KEYSTONE_BIN%/keystone-wsgi-public
     WSGIApplicationGroup %{GLOBAL}
     WSGIPassAuthorization On
     <IfVersion >= 2.4>
@@ -16,12 +16,22 @@
     %SSLENGINE%
     %SSLCERTFILE%
     %SSLKEYFILE%
+
+    <Directory %KEYSTONE_BIN%>
+        <IfVersion >= 2.4>
+            Require all granted
+        </IfVersion>
+        <IfVersion < 2.4>
+            Order allow,deny
+            Allow from all
+        </IfVersion>
+    </Directory>
 </VirtualHost>
 
 <VirtualHost *:%ADMINPORT%>
     WSGIDaemonProcess keystone-admin processes=5 threads=1 user=%USER% display-name=%{GROUP} %VIRTUALENV%
     WSGIProcessGroup keystone-admin
-    WSGIScriptAlias / %ADMINWSGI%
+    WSGIScriptAlias / %KEYSTONE_BIN%/keystone-wsgi-admin
     WSGIApplicationGroup %{GLOBAL}
     WSGIPassAuthorization On
     <IfVersion >= 2.4>
@@ -32,6 +42,16 @@
     %SSLENGINE%
     %SSLCERTFILE%
     %SSLKEYFILE%
+
+    <Directory %KEYSTONE_BIN%>
+        <IfVersion >= 2.4>
+            Require all granted
+        </IfVersion>
+        <IfVersion < 2.4>
+            Order allow,deny
+            Allow from all
+        </IfVersion>
+    </Directory>
 </VirtualHost>
 
 Alias /identity %PUBLICWSGI%
diff --git a/files/debs/zaqar-server b/files/debs/zaqar-server
deleted file mode 100644
index 6c2a4d1..0000000
--- a/files/debs/zaqar-server
+++ /dev/null
@@ -1,4 +0,0 @@
-python-pymongo
-mongodb-server
-pkg-config
-redis-server # NOPRIME
\ No newline at end of file
diff --git a/files/rpms/zaqar-server b/files/rpms/zaqar-server
deleted file mode 100644
index 78806fb..0000000
--- a/files/rpms/zaqar-server
+++ /dev/null
@@ -1,5 +0,0 @@
-selinux-policy-targeted
-mongodb
-mongodb-server
-pymongo
-redis # NOPRIME
diff --git a/functions b/functions
index 4001e9d..ff95c89 100644
--- a/functions
+++ b/functions
@@ -36,10 +36,9 @@
 # - ``FILES`` must be set to the cache dir
 # - ``GLANCE_HOSTPORT``
 #
-# upload_image image-url glance-token
+# upload_image image-url
 function upload_image {
     local image_url=$1
-    local token=$2
 
     local image image_fname image_name
 
@@ -71,7 +70,7 @@
     # OpenVZ-format images are provided as .tar.gz, but not decompressed prior to loading
     if [[ "$image_url" =~ 'openvz' ]]; then
         image_name="${image_fname%.tar.gz}"
-        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format ami --disk-format ami < "${image}"
+        openstack --os-cloud=devstack-admin image create "$image_name" --public --container-format ami --disk-format ami < "${image}"
         return
     fi
 
@@ -182,7 +181,7 @@
         vmdk_adapter_type="${props[1]:-$vmdk_adapter_type}"
         vmdk_net_adapter="${props[2]:-$vmdk_net_adapter}"
 
-        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}"
+        openstack --os-cloud=devstack-admin image create "$image_name" --public --container-format bare --disk-format vmdk --property vmware_disktype="$vmdk_disktype" --property vmware_adaptertype="$vmdk_adapter_type" --property hw_vif_model="$vmdk_net_adapter" < "${image}"
         return
     fi
 
@@ -199,8 +198,7 @@
             force_vm_mode="--property vm_mode=xen"
         fi
         openstack \
-            --os-token $token \
-            --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
+            --os-cloud=devstack-admin \
             image create \
             "$image_name" --public \
             --container-format=ovf --disk-format=vhd \
@@ -214,8 +212,7 @@
     if [[ "$image_url" =~ '.xen-raw.tgz' ]]; then
         image_name="${image_fname%.xen-raw.tgz}"
         openstack \
-            --os-token $token \
-            --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
+            --os-cloud=devstack-admin \
             image create \
             "$image_name" --public \
             --container-format=tgz --disk-format=raw \
@@ -231,8 +228,7 @@
         fi
 
         openstack \
-            --os-token $token \
-            --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT \
+            --os-cloud=devstack-admin \
             image create \
             "$image_name" --public \
             --container-format=bare --disk-format=ploop \
@@ -314,9 +310,9 @@
 
     if [ "$container_format" = "bare" ]; then
         if [ "$unpack" = "zcat" ]; then
-            openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}")
+            openstack --os-cloud=devstack-admin image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < <(zcat --force "${image}")
         else
-            openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}"
+            openstack --os-cloud=devstack-admin image create "$image_name" $img_property --public --container-format=$container_format --disk-format $disk_format < "${image}"
         fi
     else
         # Use glance client to add the kernel the root filesystem.
@@ -324,12 +320,12 @@
         # kernel for use when uploading the root filesystem.
         local kernel_id="" ramdisk_id="";
         if [ -n "$kernel" ]; then
-            kernel_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2)
+            kernel_id=$(openstack --os-cloud=devstack-admin image create "$image_name-kernel" $img_property --public --container-format aki --disk-format aki < "$kernel" | grep ' id ' | get_field 2)
         fi
         if [ -n "$ramdisk" ]; then
-            ramdisk_id=$(openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2)
+            ramdisk_id=$(openstack --os-cloud=devstack-admin image create "$image_name-ramdisk" $img_property --public --container-format ari --disk-format ari < "$ramdisk" | grep ' id ' | get_field 2)
         fi
-        openstack --os-token $token --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}"
+        openstack --os-cloud=devstack-admin image create "${image_name%.img}" $img_property --public --container-format ami --disk-format ami ${kernel_id:+--property kernel_id=$kernel_id} ${ramdisk_id:+--property ramdisk_id=$ramdisk_id} < "${image}"
     fi
 }
 
diff --git a/functions-common b/functions-common
index f6a5253..a7fec41 100644
--- a/functions-common
+++ b/functions-common
@@ -67,6 +67,45 @@
     done
 }
 
+# Update/create user clouds.yaml file.
+# clouds.yaml will have
+# - A `devstack` entry for the `demo` user for the `demo` project.
+# - A `devstack-admin` entry for the `admin` user for the `admin` project.
+# write_clouds_yaml
+function write_clouds_yaml {
+    # The location is a variable to allow for easier refactoring later to make it
+    # overridable. There is currently no usecase where doing so makes sense, so
+    # it's not currently configurable.
+    CLOUDS_YAML=~/.config/openstack/clouds.yaml
+
+    mkdir -p $(dirname $CLOUDS_YAML)
+
+    CA_CERT_ARG=''
+    if [ -f "$SSL_BUNDLE_FILE" ]; then
+        CA_CERT_ARG="--os-cacert $SSL_BUNDLE_FILE"
+    fi
+    $TOP_DIR/tools/update_clouds_yaml.py \
+        --file $CLOUDS_YAML \
+        --os-cloud devstack \
+        --os-region-name $REGION_NAME \
+        --os-identity-api-version $IDENTITY_API_VERSION \
+        $CA_CERT_ARG \
+        --os-auth-url $KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION \
+        --os-username demo \
+        --os-password $ADMIN_PASSWORD \
+        --os-project-name demo
+    $TOP_DIR/tools/update_clouds_yaml.py \
+        --file $CLOUDS_YAML \
+        --os-cloud devstack-admin \
+        --os-region-name $REGION_NAME \
+        --os-identity-api-version $IDENTITY_API_VERSION \
+        $CA_CERT_ARG \
+        --os-auth-url $KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION \
+        --os-username admin \
+        --os-password $ADMIN_PASSWORD \
+        --os-project-name admin
+}
+
 # Normalize config values to True or False
 # Accepts as False: 0 no No NO false False FALSE
 # Accepts as True: 1 yes Yes YES true True TRUE
@@ -453,8 +492,11 @@
     if echo $git_ref | egrep -q "^refs"; then
         # If our branch name is a gerrit style refs/changes/...
         if [[ ! -d $git_dest ]]; then
-            [[ "$ERROR_ON_CLONE" = "True" ]] && \
+            if [[ "$ERROR_ON_CLONE" = "True" ]]; then
+                echo "The $git_dest project was not found; if this is a gate job, add"
+                echo "the project to the \$PROJECTS variable in the job definition."
                 die $LINENO "Cloning not allowed in this configuration"
+            fi
             git_timed clone $git_clone_flags $git_remote $git_dest
         fi
         cd $git_dest
@@ -462,8 +504,11 @@
     else
         # do a full clone only if the directory doesn't exist
         if [[ ! -d $git_dest ]]; then
-            [[ "$ERROR_ON_CLONE" = "True" ]] && \
+            if [[ "$ERROR_ON_CLONE" = "True" ]]; then
+                echo "The $git_dest project was not found; if this is a gate job, add"
+                echo "the project to the \$PROJECTS variable in the job definition."
                 die $LINENO "Cloning not allowed in this configuration"
+            fi
             git_timed clone $git_clone_flags $git_remote $git_dest
             cd $git_dest
             # This checkout syntax works for both branches and tags
@@ -591,7 +636,7 @@
         host_ip=""
         # Find the interface used for the default route
         host_ip_iface=${host_ip_iface:-$(ip -f $af route | awk '/default/ {print $5}' | head -1)}
-        local host_ips=$(LC_ALL=C ip -f $af addr show ${host_ip_iface} | awk /$af'/ {split($2,parts,"/");  print parts[1]}')
+        local host_ips=$(LC_ALL=C ip -f $af addr show ${host_ip_iface} | sed /temporary/d |awk /$af'/ {split($2,parts,"/");  print parts[1]}')
         local ip
         for ip in $host_ips; do
             # Attempt to filter out IP addresses that are part of the fixed and
@@ -791,14 +836,20 @@
         --column "Name" \
         | grep " $1 " | get_field 1)
     if [[ -z "$user_role_id" ]]; then
-        # Adds role to user
-        user_role_id=$(openstack role add \
-            $1 \
+        # Adds role to user and get it
+        openstack role add $1 \
             --user $2 \
             --project $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 \
-            | grep " id " | get_field 2)
+            --column "ID" \
+            --project $3 \
+            --column "Name" \
+            | grep " $1 " | get_field 1)
     fi
     echo $user_role_id
 }
@@ -1033,10 +1084,6 @@
             if [[ ! $file_to_parse =~ $package_dir/cinder ]]; then
                 file_to_parse="${file_to_parse} ${package_dir}/cinder"
             fi
-        elif [[ $service == ceilometer-* ]]; then
-            if [[ ! $file_to_parse =~ $package_dir/ceilometer ]]; then
-                file_to_parse="${file_to_parse} ${package_dir}/ceilometer"
-            fi
         elif [[ $service == s-* ]]; then
             if [[ ! $file_to_parse =~ $package_dir/swift ]]; then
                 file_to_parse="${file_to_parse} ${package_dir}/swift"
@@ -1453,7 +1500,7 @@
         return
     fi
 
-    # Check if there is any falure flag file under $SERVICE_DIR/$SCREEN_NAME
+    # Check if there is any failure flag file under $SERVICE_DIR/$SCREEN_NAME
     # make this -o errexit safe
     failures=`ls "$SERVICE_DIR/$SCREEN_NAME"/*.failure 2>/dev/null || /bin/true`
 
@@ -1777,7 +1824,6 @@
 # There are special cases for some 'catch-all' services::
 #   **nova** returns true if any service enabled start with **n-**
 #   **cinder** returns true if any service enabled start with **c-**
-#   **ceilometer** returns true if any service enabled start with **ceilometer**
 #   **glance** returns true if any service enabled start with **g-**
 #   **neutron** returns true if any service enabled start with **q-**
 #   **swift** returns true if any service enabled start with **s-**
@@ -1803,8 +1849,7 @@
         # Look for top-level 'enabled' function for this service
         if type is_${service}_enabled >/dev/null 2>&1; then
             # A function exists for this service, use it
-            is_${service}_enabled
-            enabled=$?
+            is_${service}_enabled && enabled=0
         fi
 
         # TODO(dtroyer): Remove these legacy special-cases after the is_XXX_enabled()
@@ -1813,7 +1858,6 @@
         [[ ${service} == n-cell-* && ${ENABLED_SERVICES} =~ "n-cell" ]] && enabled=0
         [[ ${service} == n-cpu-* && ${ENABLED_SERVICES} =~ "n-cpu" ]] && enabled=0
         [[ ${service} == "nova" && ${ENABLED_SERVICES} =~ "n-" ]] && enabled=0
-        [[ ${service} == "ceilometer" && ${ENABLED_SERVICES} =~ "ceilometer-" ]] && enabled=0
         [[ ${service} == "glance" && ${ENABLED_SERVICES} =~ "g-" ]] && enabled=0
         [[ ${service} == "ironic" && ${ENABLED_SERVICES} =~ "ir-" ]] && enabled=0
         [[ ${service} == "neutron" && ${ENABLED_SERVICES} =~ "q-" ]] && enabled=0
diff --git a/inc/python b/inc/python
index 5c9dc5c..fd0d616 100644
--- a/inc/python
+++ b/inc/python
@@ -124,7 +124,7 @@
         $@
 
     # Also install test requirements
-    local test_req="$@/test-requirements.txt"
+    local test_req="${!#}/test-requirements.txt"
     if [[ -e "$test_req" ]]; then
         echo "Installing test-requirements for $test_req"
         $sudo_pip \
@@ -157,6 +157,28 @@
     return $enabled
 }
 
+# determine if a package was installed from git
+function lib_installed_from_git {
+    local name=$1
+    pip freeze 2>/dev/null | grep -- "$name" | grep -q -- '-e git'
+}
+
+# check that everything that's in LIBS_FROM_GIT was actually installed
+# correctly, this helps double check issues with library fat fingering.
+function check_libs_from_git {
+    local lib=""
+    local not_installed=""
+    for lib in $(echo ${LIBS_FROM_GIT} | tr "," " "); do
+        if ! lib_installed_from_git "$lib"; then
+            not_installed+=" $lib"
+        fi
+    done
+    # if anything is not installed, say what it is.
+    if [[ -n "$not_installed" ]]; then
+        die $LINENO "The following LIBS_FROM_GIT were not installed correct: $not_installed"
+    fi
+}
+
 # setup a library by name. 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
diff --git a/lib/ceilometer b/lib/ceilometer
deleted file mode 100644
index 3df75b7..0000000
--- a/lib/ceilometer
+++ /dev/null
@@ -1,421 +0,0 @@
-#!/bin/bash
-#
-# lib/ceilometer
-# Install and start **Ceilometer** service
-
-# To enable a minimal set of Ceilometer services, add the following to the
-# ``localrc`` section of ``local.conf``:
-#
-#   enable_service ceilometer-acompute ceilometer-acentral ceilometer-anotification ceilometer-collector ceilometer-api
-#
-# To ensure Ceilometer alarming services are enabled also, further add to the
-# localrc section of local.conf:
-#
-#   enable_service ceilometer-alarm-notifier ceilometer-alarm-evaluator
-#
-# To enable Ceilometer to collect the IPMI based meters, further add to the
-# localrc section of local.conf:
-#
-#   enable_service ceilometer-aipmi
-#
-# NOTE: Currently, there are two ways to get the IPMI based meters in
-# OpenStack. One way is to configure Ironic conductor to report those meters
-# for the nodes managed by Ironic and to have Ceilometer notification
-# agent to collect them. Ironic by default does NOT enable that reporting
-# functionality. So in order to do so, users need to set the option of
-# conductor.send_sensor_data to true in the ironic.conf configuration file
-# for the Ironic conductor service, and also enable the
-# ceilometer-anotification service.
-#
-# The other way is to use Ceilometer ipmi agent only to get the IPMI based
-# meters. To avoid duplicated meters, users need to make sure to set the
-# option of conductor.send_sensor_data to false in the ironic.conf
-# configuration file if the node on which Ceilometer ipmi agent is running
-# is also managed by Ironic.
-#
-# Several variables set in the localrc section adjust common behaviors
-# of Ceilometer (see within for additional settings):
-#
-#   CEILOMETER_USE_MOD_WSGI:       When True, run the api under mod_wsgi.
-#   CEILOMETER_PIPELINE_INTERVAL:  Seconds between pipeline processing runs. Default 600.
-#   CEILOMETER_BACKEND:            Database backend (e.g. 'mysql', 'mongodb', 'es')
-#   CEILOMETER_COORDINATION_URL:   URL for group membership service provided by tooz.
-#   CEILOMETER_EVENTS:             Enable event collection
-
-# Dependencies:
-#
-# - functions
-# - OS_AUTH_URL for auth in api
-# - DEST set to the destination directory
-# - SERVICE_PASSWORD, SERVICE_TENANT_NAME for auth in api
-# - STACK_USER service user
-
-# stack.sh
-# ---------
-# - install_ceilometer
-# - configure_ceilometer
-# - init_ceilometer
-# - start_ceilometer
-# - stop_ceilometer
-# - cleanup_ceilometer
-
-# Save trace setting
-XTRACE=$(set +o | grep xtrace)
-set +o xtrace
-
-
-# Defaults
-# --------
-
-# Set up default directories
-GITDIR["python-ceilometerclient"]=$DEST/python-ceilometerclient
-GITDIR["ceilometermiddleware"]=$DEST/ceilometermiddleware
-
-CEILOMETER_DIR=$DEST/ceilometer
-CEILOMETER_CONF_DIR=/etc/ceilometer
-CEILOMETER_CONF=$CEILOMETER_CONF_DIR/ceilometer.conf
-CEILOMETER_API_LOG_DIR=/var/log/ceilometer-api
-CEILOMETER_AUTH_CACHE_DIR=${CEILOMETER_AUTH_CACHE_DIR:-/var/cache/ceilometer}
-CEILOMETER_WSGI_DIR=${CEILOMETER_WSGI_DIR:-/var/www/ceilometer}
-
-# Support potential entry-points console scripts in VENV or not
-if [[ ${USE_VENV} = True ]]; then
-    PROJECT_VENV["ceilometer"]=${CEILOMETER_DIR}.venv
-    CEILOMETER_BIN_DIR=${PROJECT_VENV["ceilometer"]}/bin
-else
-    CEILOMETER_BIN_DIR=$(get_python_exec_prefix)
-fi
-
-# Set up database backend
-CEILOMETER_BACKEND=${CEILOMETER_BACKEND:-mysql}
-
-# Ceilometer connection info.
-CEILOMETER_SERVICE_PROTOCOL=http
-CEILOMETER_SERVICE_HOST=$SERVICE_HOST
-CEILOMETER_SERVICE_PORT=${CEILOMETER_SERVICE_PORT:-8777}
-CEILOMETER_USE_MOD_WSGI=$(trueorfalse False CEILOMETER_USE_MOD_WSGI)
-
-# To enable OSprofiler change value of this variable to "notifications,profiler"
-CEILOMETER_NOTIFICATION_TOPICS=${CEILOMETER_NOTIFICATION_TOPICS:-notifications}
-CEILOMETER_EVENTS=${CEILOMETER_EVENTS:-True}
-
-CEILOMETER_COORDINATION_URL=${CEILOMETER_COORDINATION_URL:-}
-CEILOMETER_PIPELINE_INTERVAL=${CEILOMETER_PIPELINE_INTERVAL:-}
-
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,ceilometer
-
-
-# Functions
-# ---------
-
-# Test if any Ceilometer services are enabled
-# is_ceilometer_enabled
-function is_ceilometer_enabled {
-    [[ ,${ENABLED_SERVICES} =~ ,"ceilometer-" ]] && return 0
-    return 1
-}
-
-# create_ceilometer_accounts() - Set up common required Ceilometer accounts
-#
-# Project              User         Roles
-# ------------------------------------------------------------------
-# SERVICE_TENANT_NAME  ceilometer   admin
-# SERVICE_TENANT_NAME  ceilometer   ResellerAdmin (if Swift is enabled)
-function create_ceilometer_accounts {
-
-    # Ceilometer
-    if [[ "$ENABLED_SERVICES" =~ "ceilometer-api" ]]; then
-
-        create_service_user "ceilometer" "admin"
-
-        if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
-            get_or_create_service "ceilometer" "metering" "OpenStack Telemetry Service"
-            get_or_create_endpoint "metering" \
-                "$REGION_NAME" \
-                "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT/" \
-                "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT/" \
-                "$CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT/"
-        fi
-        if is_service_enabled swift; then
-            # Ceilometer needs ResellerAdmin role to access Swift account stats.
-            get_or_add_user_project_role "ResellerAdmin" "ceilometer" $SERVICE_TENANT_NAME
-        fi
-    fi
-}
-
-
-# _cleanup_keystone_apache_wsgi() - Remove WSGI files, disable and remove Apache vhost file
-function _cleanup_ceilometer_apache_wsgi {
-    sudo rm -f $CEILOMETER_WSGI_DIR/*
-    sudo rm -f $(apache_site_config_for ceilometer)
-}
-
-# cleanup_ceilometer() - Remove residual data files, anything left over from previous
-# runs that a clean run would need to clean up
-function cleanup_ceilometer {
-    if [ "$CEILOMETER_BACKEND" = 'mongodb' ] ; then
-        mongo ceilometer --eval "db.dropDatabase();"
-    elif [ "$CEILOMETER_BACKEND" = 'es' ] ; then
-        curl -XDELETE "localhost:9200/events_*"
-    fi
-    if [ "$CEILOMETER_USE_MOD_WSGI" == "True" ]; then
-        _cleanup_ceilometer_apache_wsgi
-    fi
-}
-
-function _config_ceilometer_apache_wsgi {
-    sudo mkdir -p $CEILOMETER_WSGI_DIR
-
-    local ceilometer_apache_conf=$(apache_site_config_for ceilometer)
-    local apache_version=$(get_apache_version)
-    local venv_path=""
-
-    # Copy proxy vhost and wsgi file
-    sudo cp $CEILOMETER_DIR/ceilometer/api/app.wsgi $CEILOMETER_WSGI_DIR/app
-
-    if [[ ${USE_VENV} = True ]]; then
-        venv_path="python-path=${PROJECT_VENV["ceilometer"]}/lib/$(python_version)/site-packages"
-    fi
-
-    sudo cp $FILES/apache-ceilometer.template $ceilometer_apache_conf
-    sudo sed -e "
-        s|%PORT%|$CEILOMETER_SERVICE_PORT|g;
-        s|%APACHE_NAME%|$APACHE_NAME|g;
-        s|%WSGIAPP%|$CEILOMETER_WSGI_DIR/app|g;
-        s|%USER%|$STACK_USER|g;
-        s|%VIRTUALENV%|$venv_path|g
-    " -i $ceilometer_apache_conf
-}
-
-# configure_ceilometer() - Set config files, create data dirs, etc
-function configure_ceilometer {
-    sudo install -d -o $STACK_USER -m 755 $CEILOMETER_CONF_DIR $CEILOMETER_API_LOG_DIR
-
-    iniset_rpc_backend ceilometer $CEILOMETER_CONF
-
-    iniset $CEILOMETER_CONF DEFAULT notification_topics "$CEILOMETER_NOTIFICATION_TOPICS"
-    iniset $CEILOMETER_CONF DEFAULT verbose True
-    iniset $CEILOMETER_CONF DEFAULT debug "$ENABLE_DEBUG_LOG_LEVEL"
-
-    if [[ -n "$CEILOMETER_COORDINATION_URL" ]]; then
-        iniset $CEILOMETER_CONF coordination backend_url $CEILOMETER_COORDINATION_URL
-        iniset $CEILOMETER_CONF compute workload_partitioning True
-    fi
-
-    # Install the policy file for the API server
-    cp $CEILOMETER_DIR/etc/ceilometer/policy.json $CEILOMETER_CONF_DIR
-    iniset $CEILOMETER_CONF oslo_policy policy_file $CEILOMETER_CONF_DIR/policy.json
-
-    cp $CEILOMETER_DIR/etc/ceilometer/pipeline.yaml $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/event_pipeline.yaml $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/api_paste.ini $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/event_definitions.yaml $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_archive_policy_map.yaml $CEILOMETER_CONF_DIR
-    cp $CEILOMETER_DIR/etc/ceilometer/gnocchi_resources.yaml $CEILOMETER_CONF_DIR
-
-    if [ "$CEILOMETER_PIPELINE_INTERVAL" ]; then
-        sed -i "s/interval:.*/interval: ${CEILOMETER_PIPELINE_INTERVAL}/" $CEILOMETER_CONF_DIR/pipeline.yaml
-    fi
-
-    # The compute and central agents need these credentials in order to
-    # call out to other services' public APIs.
-    # The alarm evaluator needs these options to call ceilometer APIs
-    iniset $CEILOMETER_CONF service_credentials os_username ceilometer
-    iniset $CEILOMETER_CONF service_credentials os_password $SERVICE_PASSWORD
-    iniset $CEILOMETER_CONF service_credentials os_tenant_name $SERVICE_TENANT_NAME
-    iniset $CEILOMETER_CONF service_credentials os_region_name $REGION_NAME
-    iniset $CEILOMETER_CONF service_credentials os_auth_url $KEYSTONE_SERVICE_URI/v2.0
-
-    configure_auth_token_middleware $CEILOMETER_CONF ceilometer $CEILOMETER_AUTH_CACHE_DIR
-
-    iniset $CEILOMETER_CONF notification store_events $CEILOMETER_EVENTS
-
-    if [ "$CEILOMETER_BACKEND" = 'mysql' ] || [ "$CEILOMETER_BACKEND" = 'postgresql' ] ; then
-        iniset $CEILOMETER_CONF database alarm_connection $(database_connection_url ceilometer)
-        iniset $CEILOMETER_CONF database event_connection $(database_connection_url ceilometer)
-        iniset $CEILOMETER_CONF database metering_connection $(database_connection_url ceilometer)
-        iniset $CEILOMETER_CONF DEFAULT collector_workers $API_WORKERS
-    elif [ "$CEILOMETER_BACKEND" = 'es' ] ; then
-        # es is only supported for events. we will use sql for alarming/metering.
-        iniset $CEILOMETER_CONF database alarm_connection $(database_connection_url ceilometer)
-        iniset $CEILOMETER_CONF database event_connection es://localhost:9200
-        iniset $CEILOMETER_CONF database metering_connection $(database_connection_url ceilometer)
-        iniset $CEILOMETER_CONF DEFAULT collector_workers $API_WORKERS
-        ${TOP_DIR}/pkg/elasticsearch.sh start
-        cleanup_ceilometer
-    elif [ "$CEILOMETER_BACKEND" = 'mongodb' ] ; then
-        iniset $CEILOMETER_CONF database alarm_connection mongodb://localhost:27017/ceilometer
-        iniset $CEILOMETER_CONF database event_connection mongodb://localhost:27017/ceilometer
-        iniset $CEILOMETER_CONF database metering_connection mongodb://localhost:27017/ceilometer
-        configure_mongodb
-        cleanup_ceilometer
-    else
-        die $LINENO "Unable to configure unknown CEILOMETER_BACKEND $CEILOMETER_BACKEND"
-    fi
-
-    if [[ "$VIRT_DRIVER" = 'vsphere' ]]; then
-        iniset $CEILOMETER_CONF DEFAULT hypervisor_inspector vsphere
-        iniset $CEILOMETER_CONF vmware host_ip "$VMWAREAPI_IP"
-        iniset $CEILOMETER_CONF vmware host_username "$VMWAREAPI_USER"
-        iniset $CEILOMETER_CONF vmware host_password "$VMWAREAPI_PASSWORD"
-    fi
-
-    if [ "$CEILOMETER_USE_MOD_WSGI" == "True" ]; then
-        iniset $CEILOMETER_CONF api pecan_debug "False"
-        _config_ceilometer_apache_wsgi
-    fi
-
-    if is_service_enabled ceilometer-aipmi; then
-        # Configure rootwrap for the ipmi agent
-        configure_rootwrap ceilometer
-    fi
-}
-
-function configure_mongodb {
-    # Server package is the same on all
-    local packages=mongodb-server
-
-    if is_fedora; then
-        # mongodb client
-        packages="${packages} mongodb"
-    fi
-
-    install_package ${packages}
-
-    if is_fedora; then
-        # Ensure smallfiles is selected to minimize freespace requirements
-        sudo sed -i '/--smallfiles/!s/OPTIONS=\"/OPTIONS=\"--smallfiles /' /etc/sysconfig/mongod
-
-        restart_service mongod
-    fi
-
-    # Give mongodb time to start-up
-    sleep 5
-}
-
-# init_ceilometer() - Initialize etc.
-function init_ceilometer {
-    # Create cache dir
-    sudo install -d -o $STACK_USER $CEILOMETER_AUTH_CACHE_DIR
-    rm -f $CEILOMETER_AUTH_CACHE_DIR/*
-
-    if is_service_enabled mysql postgresql; then
-        if [ "$CEILOMETER_BACKEND" = 'mysql' ] || [ "$CEILOMETER_BACKEND" = 'postgresql' ] || [ "$CEILOMETER_BACKEND" = 'es' ] ; then
-            recreate_database ceilometer
-            $CEILOMETER_BIN_DIR/ceilometer-dbsync
-        fi
-    fi
-}
-
-# install_redis() - Install the redis server.
-function install_redis {
-    if is_ubuntu; then
-        install_package redis-server
-        restart_service redis-server
-    else
-        # This will fail (correctly) where a redis package is unavailable
-        install_package redis
-        restart_service redis
-    fi
-}
-
-# install_ceilometer() - Collect source and prepare
-function install_ceilometer {
-    git_clone $CEILOMETER_REPO $CEILOMETER_DIR $CEILOMETER_BRANCH
-    setup_develop $CEILOMETER_DIR
-
-    if echo $CEILOMETER_COORDINATION_URL | grep -q '^memcached:'; then
-        install_package memcached
-    elif echo $CEILOMETER_COORDINATION_URL | grep -q '^redis:'; then
-        install_redis
-    fi
-
-    if [ "$CEILOMETER_BACKEND" = 'mongodb' ] ; then
-        pip_install_gr pymongo
-    fi
-
-    # Only install virt drivers if we're running nova compute
-    if is_service_enabled n-cpu ; then
-        if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then
-            pip_install_gr libvirt-python
-        fi
-
-        if [[ "$VIRT_DRIVER" = 'vsphere' ]]; then
-            pip_install_gr oslo.vmware
-        fi
-    fi
-
-    if [ "$CEILOMETER_BACKEND" = 'es' ] ; then
-        ${TOP_DIR}/pkg/elasticsearch.sh download
-        ${TOP_DIR}/pkg/elasticsearch.sh install
-    fi
-}
-
-# install_ceilometerclient() - Collect source and prepare
-function install_ceilometerclient {
-    if use_library_from_git "python-ceilometerclient"; then
-        git_clone_by_name "python-ceilometerclient"
-        setup_dev_lib "python-ceilometerclient"
-        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ceilometerclient"]}/tools/,/etc/bash_completion.d/}ceilometer.bash_completion
-    fi
-}
-
-# start_ceilometer() - Start running processes, including screen
-function start_ceilometer {
-    run_process ceilometer-acentral "$CEILOMETER_BIN_DIR/ceilometer-agent-central --config-file $CEILOMETER_CONF"
-    run_process ceilometer-anotification "$CEILOMETER_BIN_DIR/ceilometer-agent-notification --config-file $CEILOMETER_CONF"
-    run_process ceilometer-collector "$CEILOMETER_BIN_DIR/ceilometer-collector --config-file $CEILOMETER_CONF"
-    run_process ceilometer-aipmi "$CEILOMETER_BIN_DIR/ceilometer-agent-ipmi --config-file $CEILOMETER_CONF"
-
-    if [[ "$CEILOMETER_USE_MOD_WSGI" == "False" ]]; then
-        run_process ceilometer-api "$CEILOMETER_BIN_DIR/ceilometer-api -d -v --log-dir=$CEILOMETER_API_LOG_DIR --config-file $CEILOMETER_CONF"
-    else
-        enable_apache_site ceilometer
-        restart_apache_server
-        tail_log ceilometer /var/log/$APACHE_NAME/ceilometer.log
-        tail_log ceilometer-api /var/log/$APACHE_NAME/ceilometer_access.log
-    fi
-
-
-    # Start the compute agent last to allow time for the collector to
-    # fully wake up and connect to the message bus. See bug #1355809
-    if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then
-        run_process ceilometer-acompute "$CEILOMETER_BIN_DIR/ceilometer-agent-compute --config-file $CEILOMETER_CONF" $LIBVIRT_GROUP
-    fi
-    if [[ "$VIRT_DRIVER" = 'vsphere' ]]; then
-        run_process ceilometer-acompute "$CEILOMETER_BIN_DIR/ceilometer-agent-compute --config-file $CEILOMETER_CONF"
-    fi
-
-    # Only die on API if it was actually intended to be turned on
-    if is_service_enabled ceilometer-api; then
-        echo "Waiting for ceilometer-api to start..."
-        if ! wait_for_service $SERVICE_TIMEOUT $CEILOMETER_SERVICE_PROTOCOL://$CEILOMETER_SERVICE_HOST:$CEILOMETER_SERVICE_PORT/v2/; then
-            die $LINENO "ceilometer-api did not start"
-        fi
-    fi
-
-    run_process ceilometer-alarm-notifier "$CEILOMETER_BIN_DIR/ceilometer-alarm-notifier --config-file $CEILOMETER_CONF"
-    run_process ceilometer-alarm-evaluator "$CEILOMETER_BIN_DIR/ceilometer-alarm-evaluator --config-file $CEILOMETER_CONF"
-}
-
-# stop_ceilometer() - Stop running processes
-function stop_ceilometer {
-    if [ "$CEILOMETER_USE_MOD_WSGI" == "True" ]; then
-        disable_apache_site ceilometer
-        restart_apache_server
-    fi
-    # Kill the ceilometer screen windows
-    for serv in ceilometer-acompute ceilometer-acentral ceilometer-aipmi ceilometer-anotification ceilometer-collector ceilometer-api ceilometer-alarm-notifier ceilometer-alarm-evaluator; do
-        stop_process $serv
-    done
-}
-
-
-# Restore xtrace
-$XTRACE
-
-# Tell emacs to use shell-script-mode
-## Local variables:
-## mode: shell-script
-## End:
diff --git a/lib/cinder b/lib/cinder
index e5ed2db..1014411 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -108,9 +108,8 @@
 
 CINDER_ISCSI_HELPER=${CINDER_ISCSI_HELPER:-tgtadm}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,cinder
-
+# Toggle for deploying Cinder under HTTPD + mod_wsgi
+CINDER_USE_MOD_WSGI=${CINDER_USE_MOD_WSGI:-False}
 
 # Source the enabled backends
 if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
@@ -140,6 +139,11 @@
     return 1
 }
 
+# _cinder_cleanup_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
+function _cinder_cleanup_apache_wsgi {
+    sudo rm -f $(apache_site_config_for osapi-volume)
+}
+
 # cleanup_cinder() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_cinder {
@@ -186,6 +190,43 @@
             fi
         done
     fi
+
+    if [ "$CINDER_USE_MOD_WSGI" == "True" ]; then
+        _cinder_cleanup_apache_wsgi
+    fi
+}
+
+# _cinder_config_apache_wsgi() - Set WSGI config files
+function _cinder_config_apache_wsgi {
+    local cinder_apache_conf=$(apache_site_config_for osapi-volume)
+    local cinder_ssl=""
+    local cinder_certfile=""
+    local cinder_keyfile=""
+    local cinder_api_port=$CINDER_SERVICE_PORT
+    local venv_path=""
+
+    if is_ssl_enabled_service c-api; then
+        cinder_ssl="SSLEngine On"
+        cinder_certfile="SSLCertificateFile $CINDER_SSL_CERT"
+        cinder_keyfile="SSLCertificateKeyFile $CINDER_SSL_KEY"
+    fi
+    if [[ ${USE_VENV} = True ]]; then
+        venv_path="python-path=${PROJECT_VENV["cinder"]}/lib/python2.7/site-packages"
+    fi
+
+    # copy proxy vhost file
+    sudo cp $FILES/apache-cinder-api.template $cinder_apache_conf
+    sudo sed -e "
+        s|%PUBLICPORT%|$cinder_api_port|g;
+        s|%APACHE_NAME%|$APACHE_NAME|g;
+        s|%APIWORKERS%|$API_WORKERS|g
+        s|%CINDER_BIN_DIR%|$CINDER_BIN_DIR|g;
+        s|%SSLENGINE%|$cinder_ssl|g;
+        s|%SSLCERTFILE%|$cinder_certfile|g;
+        s|%SSLKEYFILE%|$cinder_keyfile|g;
+        s|%USER%|$STACK_USER|g;
+        s|%VIRTUALENV%|$venv_path|g
+    " -i $cinder_apache_conf
 }
 
 # configure_cinder() - Set config files, create data dirs, etc
@@ -279,13 +320,17 @@
     fi
 
     # Format logging
-    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
+    if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ] && [ "$CINDER_USE_MOD_WSGI" == "False" ]; then
         setup_colorized_logging $CINDER_CONF DEFAULT "project_id" "user_id"
     else
         # Set req-id, project-name and resource in log format
         iniset $CINDER_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(project_name)s] %(resource)s%(message)s"
     fi
 
+    if [ "$CINDER_USE_MOD_WSGI" == "True" ]; then
+        _cinder_config_apache_wsgi
+    fi
+
     if [[ -r $CINDER_PLUGINS/$CINDER_DRIVER ]]; then
         configure_cinder_driver
     fi
@@ -402,6 +447,13 @@
             install_package tgt
         fi
     fi
+
+    if [ "$CINDER_USE_MOD_WSGI" == "True" ]; then
+        install_apache_wsgi
+        if is_ssl_enabled_service "c-api"; then
+            enable_mod_ssl
+        fi
+    fi
 }
 
 # install_cinderclient() - Collect source and prepare
@@ -449,10 +501,16 @@
         fi
     fi
 
-    run_process c-api "$CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF"
-    echo "Waiting for Cinder API to start..."
-    if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$CINDER_SERVICE_HOST:$service_port; then
-        die $LINENO "c-api did not start"
+    if [ "$CINDER_USE_MOD_WSGI" == "True" ]; then
+        enable_apache_site osapi-volume
+        restart_apache_server
+        tail_log c-api /var/log/$APACHE_NAME/c-api.log
+    else
+        run_process c-api "$CINDER_BIN_DIR/cinder-api --config-file $CINDER_CONF"
+        echo "Waiting for Cinder API to start..."
+        if ! wait_for_service $SERVICE_TIMEOUT $service_protocol://$CINDER_SERVICE_HOST:$service_port; then
+            die $LINENO "c-api did not start"
+        fi
     fi
 
     run_process c-sch "$CINDER_BIN_DIR/cinder-scheduler --config-file $CINDER_CONF"
@@ -471,9 +529,16 @@
 
 # stop_cinder() - Stop running processes
 function stop_cinder {
+    if [ "$CINDER_USE_MOD_WSGI" == "True" ]; then
+        disable_apache_site osapi-volume
+        restart_apache_server
+    else
+        stop_process c-api
+    fi
+
     # Kill the cinder screen windows
     local serv
-    for serv in c-api c-bak c-sch c-vol; do
+    for serv in c-bak c-sch c-vol; do
         stop_process $serv
     done
 }
diff --git a/lib/database b/lib/database
index 5bbbe31..13740b9 100644
--- a/lib/database
+++ b/lib/database
@@ -101,7 +101,7 @@
     # a multi-node DevStack installation.
 
     # NOTE: Don't specify ``/db`` in this string so we can use it for multiple services
-    BASE_SQL_CONN=${BASE_SQL_CONN:-$(get_database_type)://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOST}
+    BASE_SQL_CONN=${BASE_SQL_CONN:-$(get_database_type_$DATABASE_TYPE)://$DATABASE_USER:$DATABASE_PASSWORD@$DATABASE_HOST}
 
     return 0
 }
@@ -135,14 +135,6 @@
     database_connection_url_$DATABASE_TYPE $db
 }
 
-function get_database_type {
-    if [[ -n "${SQLALCHEMY_DATABASE_DRIVER}" ]]; then
-        echo "${DATABASE_TYPE}+${SQLALCHEMY_DATABASE_DRIVER}"
-    else
-        echo "${DATABASE_TYPE}"
-    fi
-}
-
 
 # Restore xtrace
 $XTRACE
diff --git a/lib/databases/mysql b/lib/databases/mysql
index 7ae9a93..c2ab32e 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -12,12 +12,6 @@
 set +o xtrace
 
 MYSQL_DRIVER=${MYSQL_DRIVER:-PyMySQL}
-# Force over to pymysql driver by default if we are using it.
-if is_service_enabled mysql; then
-    if [[ "$MYSQL_DRIVER" == "PyMySQL" ]]; then
-        SQLALCHEMY_DATABASE_DRIVER=${SQLALCHEMY_DATABASE_DRIVER:-"pymysql"}
-    fi
-fi
 
 register_database mysql
 
@@ -30,6 +24,14 @@
 # Functions
 # ---------
 
+function get_database_type_mysql {
+    if [[ "$MYSQL_DRIVER" == "PyMySQL" ]]; then
+        echo mysql+pymysql
+    else
+        echo mysql
+    fi
+}
+
 # Get rid of everything enough to cleanly change database backends
 function cleanup_database_mysql {
     stop_service $MYSQL
@@ -92,14 +94,12 @@
 
     # Change bind-address from localhost (127.0.0.1) to any (::) and
     # set default db type to InnoDB
-    sudo bash -c "source $TOP_DIR/functions && \
-        iniset $my_conf mysqld bind-address "$SERVICE_LISTEN_ADDRESS" && \
-        iniset $my_conf mysqld sql_mode STRICT_ALL_TABLES && \
-        iniset $my_conf mysqld default-storage-engine InnoDB && \
-        iniset $my_conf mysqld max_connections 1024 && \
-        iniset $my_conf mysqld query_cache_type OFF && \
-        iniset $my_conf mysqld query_cache_size 0"
-
+    iniset -sudo $my_conf mysqld bind-address "$SERVICE_LISTEN_ADDRESS"
+    iniset -sudo $my_conf mysqld sql_mode STRICT_ALL_TABLES
+    iniset -sudo $my_conf mysqld default-storage-engine InnoDB
+    iniset -sudo $my_conf mysqld max_connections 1024
+    iniset -sudo $my_conf mysqld query_cache_type OFF
+    iniset -sudo $my_conf mysqld query_cache_size 0
 
     if [[ "$DATABASE_QUERY_LOGGING" == "True" ]]; then
         echo_summary "Enabling MySQL query logging"
@@ -115,12 +115,10 @@
 
         # Turn on slow query log, log all queries (any query taking longer than
         # 0 seconds) and log all non-indexed queries
-        sudo bash -c "source $TOP_DIR/functions && \
-            iniset $my_conf mysqld slow-query-log 1 && \
-            iniset $my_conf mysqld slow-query-log-file $slow_log && \
-            iniset $my_conf mysqld long-query-time 0 && \
-            iniset $my_conf mysqld log-queries-not-using-indexes 1"
-
+        iniset -sudo $my_conf mysqld slow-query-log 1
+        iniset -sudo $my_conf mysqld slow-query-log-file $slow_log
+        iniset -sudo $my_conf mysqld long-query-time 0
+        iniset -sudo $my_conf mysqld log-queries-not-using-indexes 1
     fi
 
     restart_service $mysql
diff --git a/lib/databases/postgresql b/lib/databases/postgresql
index e087a1e..78c7bed 100644
--- a/lib/databases/postgresql
+++ b/lib/databases/postgresql
@@ -21,6 +21,10 @@
 # Functions
 # ---------
 
+function get_database_type_postgresql {
+    echo postgresql
+}
+
 # Get rid of everything enough to cleanly change database backends
 function cleanup_database_postgresql {
     stop_service postgresql
diff --git a/lib/glance b/lib/glance
index b1b0f32..7be3a84 100644
--- a/lib/glance
+++ b/lib/glance
@@ -75,9 +75,6 @@
 GLANCE_SEARCH_PORT_INT=${GLANCE_SEARCH_PORT_INT:-19393}
 GLANCE_SEARCH_HOSTPORT=${GLANCE_SEARCH_HOSTPORT:-$GLANCE_SERVICE_HOST:$GLANCE_SEARCH_PORT}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,glance
-
 # Functions
 # ---------
 
diff --git a/lib/heat b/lib/heat
index cedddd2..3e6975a 100644
--- a/lib/heat
+++ b/lib/heat
@@ -53,6 +53,8 @@
 HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP}
 HEAT_API_PORT=${HEAT_API_PORT:-8004}
 
+# Support entry points installation of console scripts
+HEAT_BIN_DIR=$(get_python_exec_prefix)
 
 # other default options
 if [[ "$HEAT_STANDALONE" = "True" ]]; then
@@ -64,10 +66,6 @@
     HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-trusts}
 fi
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,heat
-
-
 # Functions
 # ---------
 
@@ -190,7 +188,7 @@
     # (re)create heat database
     recreate_database heat
 
-    $HEAT_DIR/bin/heat-manage db_sync
+    $HEAT_BIN_DIR/heat-manage db_sync
     create_heat_cache_dir
 }
 
@@ -227,10 +225,10 @@
 
 # start_heat() - Start running processes, including screen
 function start_heat {
-    run_process h-eng "$HEAT_DIR/bin/heat-engine --config-file=$HEAT_CONF"
-    run_process h-api "$HEAT_DIR/bin/heat-api --config-file=$HEAT_CONF"
-    run_process h-api-cfn "$HEAT_DIR/bin/heat-api-cfn --config-file=$HEAT_CONF"
-    run_process h-api-cw "$HEAT_DIR/bin/heat-api-cloudwatch --config-file=$HEAT_CONF"
+    run_process h-eng "$HEAT_BIN_DIR/heat-engine --config-file=$HEAT_CONF"
+    run_process h-api "$HEAT_BIN_DIR/heat-api --config-file=$HEAT_CONF"
+    run_process h-api-cfn "$HEAT_BIN_DIR/heat-api-cfn --config-file=$HEAT_CONF"
+    run_process h-api-cw "$HEAT_BIN_DIR/heat-api-cloudwatch --config-file=$HEAT_CONF"
 }
 
 # stop_heat() - Stop running processes
diff --git a/lib/horizon b/lib/horizon
index 9fe0aa8..b2539d1 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -35,10 +35,6 @@
 # The example file in Horizon repo is used by default.
 HORIZON_SETTINGS=${HORIZON_SETTINGS:-$HORIZON_DIR/openstack_dashboard/local/local_settings.py.example}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,horizon
-
-
 # Functions
 # ---------
 
diff --git a/lib/infra b/lib/infra
index 89397de..ab32efe 100644
--- a/lib/infra
+++ b/lib/infra
@@ -41,7 +41,7 @@
     # Install pbr
     if use_library_from_git "pbr"; then
         git_clone_by_name "pbr"
-        setup_lib "pbr"
+        setup_dev_lib "pbr"
     else
         # Always upgrade pbr to latest version as we may have pulled it
         # in via system packages.
diff --git a/lib/ironic b/lib/ironic
index b3ad586..40475e0 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -31,6 +31,7 @@
 
 # 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
@@ -114,9 +115,6 @@
 IRONIC_SERVICE_PORT=${IRONIC_SERVICE_PORT:-6385}
 IRONIC_HOSTPORT=${IRONIC_HOSTPORT:-$SERVICE_HOST:$IRONIC_SERVICE_PORT}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,ironic
-
 # Enable iPXE
 IRONIC_IPXE_ENABLED=$(trueorfalse False IRONIC_IPXE_ENABLED)
 IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
@@ -191,6 +189,12 @@
             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
 
@@ -505,9 +509,9 @@
     sleep 10
 
     if  [[ "$Q_USE_NAMESPACE" = "True" ]]; then
-        local tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -b2-)
+        local tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -d'@' -f1 | cut -b2-)
     else
-        local tapdev=$(sudo ip link list | grep " tap" | cut -d':' -f2 | cut -b2-)
+        local tapdev=$(sudo ip link list | grep " tap" | cut -d':' -f2 | cut -d'@' -f1 | cut -b2-)
     fi
     local tag_id=$(sudo ovs-vsctl show |grep ${tapdev} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
 
diff --git a/lib/keystone b/lib/keystone
index e2448c9..ec28b46 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -51,11 +51,6 @@
 KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/keystone}
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
 KEYSTONE_PASTE_INI=${KEYSTONE_PASTE_INI:-$KEYSTONE_CONF_DIR/keystone-paste.ini}
-if is_suse; then
-    KEYSTONE_WSGI_DIR=${KEYSTONE_WSGI_DIR:-/srv/www/htdocs/keystone}
-else
-    KEYSTONE_WSGI_DIR=${KEYSTONE_WSGI_DIR:-/var/www/keystone}
-fi
 
 # Set up additional extensions, such as oauth1, federation
 # Example of KEYSTONE_EXTENSIONS=oauth1,federation
@@ -132,14 +127,11 @@
 
 # _cleanup_keystone_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
 function _cleanup_keystone_apache_wsgi {
-    sudo rm -f $KEYSTONE_WSGI_DIR/*
     sudo rm -f $(apache_site_config_for keystone)
 }
 
 # _config_keystone_apache_wsgi() - Set WSGI config files of Keystone
 function _config_keystone_apache_wsgi {
-    sudo mkdir -p $KEYSTONE_WSGI_DIR
-
     local keystone_apache_conf=$(apache_site_config_for keystone)
     local keystone_ssl=""
     local keystone_certfile=""
@@ -161,22 +153,17 @@
         venv_path="python-path=${PROJECT_VENV["keystone"]}/lib/$(python_version)/site-packages"
     fi
 
-    # copy proxy vhost and wsgi file
-    sudo cp $KEYSTONE_DIR/httpd/keystone.py $KEYSTONE_WSGI_DIR/main
-    sudo cp $KEYSTONE_DIR/httpd/keystone.py $KEYSTONE_WSGI_DIR/admin
-
     sudo cp $FILES/apache-keystone.template $keystone_apache_conf
     sudo sed -e "
         s|%PUBLICPORT%|$keystone_service_port|g;
         s|%ADMINPORT%|$keystone_auth_port|g;
         s|%APACHE_NAME%|$APACHE_NAME|g;
-        s|%PUBLICWSGI%|$KEYSTONE_WSGI_DIR/main|g;
-        s|%ADMINWSGI%|$KEYSTONE_WSGI_DIR/admin|g;
         s|%SSLENGINE%|$keystone_ssl|g;
         s|%SSLCERTFILE%|$keystone_certfile|g;
         s|%SSLKEYFILE%|$keystone_keyfile|g;
         s|%USER%|$STACK_USER|g;
         s|%VIRTUALENV%|$venv_path|g
+        s|%KEYSTONE_BIN%|$KEYSTONE_BIN_DIR|g
     " -i $keystone_apache_conf
 }
 
@@ -353,7 +340,7 @@
 # Group                Users      Roles                 Tenant
 # ------------------------------------------------------------------
 # admins               admin      admin                 admin
-# nonadmin             demo       Member, anotherrole   demo
+# nonadmins            demo       Member, anotherrole   demo
 
 
 # Migrated from keystone_data.sh
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
old mode 100644
new mode 100755
index d0eb0c0..e67bd4a
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -158,8 +158,6 @@
 Q_USE_DEBUG_COMMAND=${Q_USE_DEBUG_COMMAND:-False}
 # The name of the default q-l3 router
 Q_ROUTER_NAME=${Q_ROUTER_NAME:-router1}
-# nova vif driver that all plugins should use
-NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
 Q_NOTIFY_NOVA_PORT_STATUS_CHANGES=${Q_NOTIFY_NOVA_PORT_STATUS_CHANGES:-True}
 Q_NOTIFY_NOVA_PORT_DATA_CHANGES=${Q_NOTIFY_NOVA_PORT_DATA_CHANGES:-True}
 VIF_PLUGGING_IS_FATAL=${VIF_PLUGGING_IS_FATAL:-True}
@@ -328,7 +326,9 @@
 # ---------------------------------
 
 # Please refer to ``lib/neutron_plugins/README.md`` for details.
-source $TOP_DIR/lib/neutron_plugins/$Q_PLUGIN
+if [ -f $TOP_DIR/lib/neutron_plugins/$Q_PLUGIN ]; then
+    source $TOP_DIR/lib/neutron_plugins/$Q_PLUGIN
+fi
 
 # Agent loadbalancer service plugin functions
 # -------------------------------------------
@@ -358,10 +358,6 @@
     Q_USE_SECGROUP=False
 fi
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,neutron
-
-
 # Save trace setting
 XTRACE=$(set +o | grep xtrace)
 set +o xtrace
@@ -495,10 +491,9 @@
         iniset $NOVA_CONF DEFAULT security_group_api neutron
     fi
 
-    # set NOVA_VIF_DRIVER and optionally set options in nova_conf
+    # optionally set options in nova_conf
     neutron_plugin_create_nova_conf
 
-    iniset $NOVA_CONF libvirt vif_driver "$NOVA_VIF_DRIVER"
     iniset $NOVA_CONF DEFAULT linuxnet_interface_driver "$LINUXNET_VIF_DRIVER"
     if is_service_enabled q-meta; then
         iniset $NOVA_CONF neutron service_metadata_proxy "True"
@@ -619,16 +614,6 @@
     recreate_database $Q_DB_NAME
     # Run Neutron db migrations
     $NEUTRON_BIN_DIR/neutron-db-manage --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
-    for svc in fwaas lbaas vpnaas; do
-        if [ "$svc" = "vpnaas" ]; then
-            q_svc="q-vpn"
-        else
-            q_svc="q-$svc"
-        fi
-        if is_service_enabled $q_svc; then
-            $NEUTRON_BIN_DIR/neutron-db-manage --service $svc --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE upgrade head
-        fi
-    done
 }
 
 # install_neutron() - Collect source and prepare
@@ -702,7 +687,7 @@
         service_protocol="http"
     fi
     # Start the Neutron service
-    run_process q-svc "python $NEUTRON_BIN_DIR/neutron-server $cfg_file_options"
+    run_process q-svc "$NEUTRON_BIN_DIR/neutron-server $cfg_file_options"
     echo "Waiting for Neutron to start..."
     if is_ssl_enabled_service "neutron"; then
         ssl_ca="--ca-certificate=${SSL_BUNDLE_FILE}"
@@ -720,7 +705,7 @@
 # Control of the l2 agent is separated out to make it easier to test partial
 # upgrades (everything upgraded except the L2 agent)
 function start_neutron_l2_agent {
-    run_process q-agt "python $AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
+    run_process q-agt "$AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
 
     if is_provider_network; then
         sudo ovs-vsctl --no-wait -- --may-exist add-port $OVS_PHYSICAL_BRIDGE $PUBLIC_INTERFACE
@@ -738,23 +723,23 @@
 }
 
 function start_neutron_other_agents {
-    run_process q-dhcp "python $AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
+    run_process q-dhcp "$AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
 
     if is_service_enabled neutron-vpnaas; then
         :  # Started by plugin
     elif is_service_enabled q-vpn; then
         run_process q-vpn "$AGENT_VPN_BINARY $(determine_config_files neutron-vpn-agent)"
     else
-        run_process q-l3 "python $AGENT_L3_BINARY $(determine_config_files neutron-l3-agent)"
+        run_process q-l3 "$AGENT_L3_BINARY $(determine_config_files neutron-l3-agent)"
     fi
 
-    run_process q-meta "python $AGENT_META_BINARY --config-file $NEUTRON_CONF --config-file=$Q_META_CONF_FILE"
-    run_process q-lbaas "python $AGENT_LBAAS_BINARY --config-file $NEUTRON_CONF --config-file=$LBAAS_AGENT_CONF_FILENAME"
-    run_process q-metering "python $AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME"
+    run_process q-meta "$AGENT_META_BINARY --config-file $NEUTRON_CONF --config-file=$Q_META_CONF_FILE"
+    run_process q-lbaas "$AGENT_LBAAS_BINARY --config-file $NEUTRON_CONF --config-file=$LBAAS_AGENT_CONF_FILENAME"
+    run_process q-metering "$AGENT_METERING_BINARY --config-file $NEUTRON_CONF --config-file $METERING_AGENT_CONF_FILENAME"
 
     if [ "$VIRT_DRIVER" = 'xenserver' ]; then
         # For XenServer, start an agent for the domU openvswitch
-        run_process q-domua "python $AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE.domU"
+        run_process q-domua "$AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE.domU"
     fi
 }
 
@@ -841,11 +826,11 @@
         fi
 
         if [[ "$IP_BRD" != "" ]]; then
-            IP_ADD="sudo ip addr del $IP_BRD dev $from_intf"
-            IP_DEL="sudo ip addr add $IP_BRD dev $to_intf"
+            IP_DEL="sudo ip addr del $IP_BRD dev $from_intf"
+            IP_ADD="sudo ip addr add $IP_BRD dev $to_intf"
         fi
 
-        $IP_ADD; $IP_DEL; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
+        $IP_DEL; $IP_ADD; $ADD_OVS_PORT; $ADD_DEFAULT_ROUTE
     fi
 }
 
@@ -916,7 +901,11 @@
     # If needed, move config file from ``$NEUTRON_DIR/etc/neutron`` to ``NEUTRON_CONF_DIR``
     mkdir -p /$Q_PLUGIN_CONF_PATH
     Q_PLUGIN_CONF_FILE=$Q_PLUGIN_CONF_PATH/$Q_PLUGIN_CONF_FILENAME
-    cp $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE /$Q_PLUGIN_CONF_FILE
+    # 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
+        cp $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE /$Q_PLUGIN_CONF_FILE
+    fi
 
     iniset $NEUTRON_CONF database connection `database_connection_url $Q_DB_NAME`
     iniset $NEUTRON_CONF DEFAULT state_path $DATA_DIR/neutron
diff --git a/lib/neutron_plugins/README.md b/lib/neutron_plugins/README.md
index 4b220d3..f03000e 100644
--- a/lib/neutron_plugins/README.md
+++ b/lib/neutron_plugins/README.md
@@ -16,9 +16,7 @@
 ``lib/neutron-legacy`` calls the following functions when the ``$Q_PLUGIN`` is enabled
 
 * ``neutron_plugin_create_nova_conf`` :
-  set ``NOVA_VIF_DRIVER`` and optionally set options in nova_conf
-  e.g.
-  NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
+  optionally set options in nova_conf
 * ``neutron_plugin_install_agent_packages`` :
   install packages that is specific to plugin agent
   e.g.
diff --git a/lib/neutron_plugins/brocade b/lib/neutron_plugins/brocade
index b8166d9..557b94d 100644
--- a/lib/neutron_plugins/brocade
+++ b/lib/neutron_plugins/brocade
@@ -12,7 +12,7 @@
 }
 
 function neutron_plugin_create_nova_conf {
-    NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
+    :
 }
 
 function neutron_plugin_install_agent_packages {
diff --git a/lib/neutron_plugins/ibm b/lib/neutron_plugins/ibm
index 3660a9f..dd5cfa6 100644
--- a/lib/neutron_plugins/ibm
+++ b/lib/neutron_plugins/ibm
@@ -42,7 +42,6 @@
 }
 
 function neutron_plugin_create_nova_conf {
-    NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
     # if n-cpu is enabled, then setup integration bridge
     if is_service_enabled n-cpu; then
         neutron_setup_integration_bridge
diff --git a/lib/neutron_plugins/linuxbridge_agent b/lib/neutron_plugins/linuxbridge_agent
index fefc1c3..bd4438d 100755
--- a/lib/neutron_plugins/linuxbridge_agent
+++ b/lib/neutron_plugins/linuxbridge_agent
@@ -69,6 +69,18 @@
     fi
     AGENT_BINARY="$NEUTRON_BIN_DIR/neutron-linuxbridge-agent"
     iniset /$Q_PLUGIN_CONF_FILE agent tunnel_types $Q_TUNNEL_TYPES
+
+    # Configure vxlan tunneling
+    if [[ "$ENABLE_TENANT_TUNNELS" == "True" ]]; then
+        if [[ "$Q_ML2_TENANT_NETWORK_TYPE" == "vxlan" ]]; then
+            iniset /$Q_PLUGIN_CONF_FILE vxlan enable_vxlan "True"
+            iniset /$Q_PLUGIN_CONF_FILE vxlan local_ip $TUNNEL_ENDPOINT_IP
+        else
+            iniset /$Q_PLUGIN_CONF_FILE vxlan enable_vxlan "False"
+        fi
+    else
+        iniset /$Q_PLUGIN_CONF_FILE vxlan enable_vxlan "False"
+    fi
 }
 
 function neutron_plugin_setup_interface_driver {
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index 13ffee9..ace5335 100755
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -19,7 +19,9 @@
 
 # Default openvswitch L2 agent
 Q_AGENT=${Q_AGENT:-openvswitch}
-source $TOP_DIR/lib/neutron_plugins/${Q_AGENT}_agent
+if [ -f $TOP_DIR/lib/neutron_plugins/${Q_AGENT}_agent ]; then
+    source $TOP_DIR/lib/neutron_plugins/${Q_AGENT}_agent
+fi
 
 # List of MechanismDrivers to load
 Q_ML2_PLUGIN_MECHANISM_DRIVERS=${Q_ML2_PLUGIN_MECHANISM_DRIVERS:-openvswitch,linuxbridge}
diff --git a/lib/neutron_plugins/nuage b/lib/neutron_plugins/nuage
index 7bce233..9e5307b 100644
--- a/lib/neutron_plugins/nuage
+++ b/lib/neutron_plugins/nuage
@@ -10,7 +10,6 @@
 function neutron_plugin_create_nova_conf {
     NOVA_OVS_BRIDGE=${NOVA_OVS_BRIDGE:-"br-int"}
     iniset $NOVA_CONF neutron ovs_bridge $NOVA_OVS_BRIDGE
-    NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
     LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver
     iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER
 }
diff --git a/lib/neutron_plugins/ofagent_agent b/lib/neutron_plugins/ofagent_agent
deleted file mode 100644
index 0bc9bff..0000000
--- a/lib/neutron_plugins/ofagent_agent
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-# REVISIT(yamamoto): This file is intentionally left empty
-# in order to keep Q_AGENT=ofagent_agent work.
diff --git a/lib/neutron_plugins/oneconvergence b/lib/neutron_plugins/oneconvergence
index 48a368a..0c570e5 100644
--- a/lib/neutron_plugins/oneconvergence
+++ b/lib/neutron_plugins/oneconvergence
@@ -68,7 +68,6 @@
 }
 
 function neutron_plugin_create_nova_conf {
-    NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
     if ( is_service_enabled n-cpu && ! ( is_service_enabled q-dhcp )) ; then
         setup_integration_bridge
     fi
diff --git a/lib/neutron_plugins/openvswitch_agent b/lib/neutron_plugins/openvswitch_agent
index 1ff3a40..48e47b3 100755
--- a/lib/neutron_plugins/openvswitch_agent
+++ b/lib/neutron_plugins/openvswitch_agent
@@ -105,6 +105,7 @@
         iniset "/$Q_PLUGIN_CONF_FILE.domU" agent root_helper "$Q_RR_COMMAND"
     fi
     iniset /$Q_PLUGIN_CONF_FILE agent tunnel_types $Q_TUNNEL_TYPES
+    iniset /$Q_PLUGIN_CONF_FILE ovs datapath_type $OVS_DATAPATH_TYPE
 }
 
 function neutron_plugin_setup_interface_driver {
diff --git a/lib/neutron_plugins/ovs_base b/lib/neutron_plugins/ovs_base
index f1f7f85..b012683 100755
--- a/lib/neutron_plugins/ovs_base
+++ b/lib/neutron_plugins/ovs_base
@@ -8,7 +8,8 @@
 set +o xtrace
 
 OVS_BRIDGE=${OVS_BRIDGE:-br-int}
-OVS_DATAPATH_TYPE=${OVS_DATAPATH_TYPE:-""}
+# OVS recognize default 'system' datapath or 'netdev' for userspace datapath
+OVS_DATAPATH_TYPE=${OVS_DATAPATH_TYPE:-system}
 OVS_TUNNEL_BRIDGE=${OVS_TUNNEL_BRIDGE:-br-tun}
 
 function is_neutron_ovs_base_plugin {
@@ -20,7 +21,7 @@
     local bridge=$1
     local addbr_cmd="sudo ovs-vsctl --no-wait -- --may-exist add-br $bridge"
 
-    if [ "$OVS_DATAPATH_TYPE" != "" ] ; then
+    if [ "$OVS_DATAPATH_TYPE" != "system" ] ; then
         addbr_cmd="$addbr_cmd -- set Bridge $bridge datapath_type=${OVS_DATAPATH_TYPE}"
     fi
 
diff --git a/lib/nova b/lib/nova
index c0227c5..9830276 100644
--- a/lib/nova
+++ b/lib/nova
@@ -165,10 +165,6 @@
 TEST_FLOATING_POOL=${TEST_FLOATING_POOL:-test}
 TEST_FLOATING_RANGE=${TEST_FLOATING_RANGE:-192.168.253.0/29}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,nova
-
-
 # Functions
 # ---------
 
@@ -332,7 +328,7 @@
                 if [ ! -e /dev/kvm ]; then
                     echo "WARNING: Switching to QEMU"
                     LIBVIRT_TYPE=qemu
-                    if which selinuxenabled 2>&1 > /dev/null && selinuxenabled; then
+                    if which selinuxenabled >/dev/null 2>&1 && selinuxenabled; then
                         # https://bugzilla.redhat.com/show_bug.cgi?id=753589
                         sudo setsebool virt_use_execmem on
                     fi
@@ -354,6 +350,12 @@
                             sudo mount /cgroup
                         fi
                     fi
+
+                    # enable nbd for lxc unless you're using an lvm backend
+                    # otherwise you can't boot instances
+                    if [[ "$NOVA_BACKEND" != "LVM" ]]; then
+                        sudo modprobe nbd
+                    fi
                 fi
             fi
         fi
@@ -606,6 +608,8 @@
     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"
 
     iniset $NOVA_CONF cinder os_region_name "$REGION_NAME"
 
diff --git a/lib/nova_plugins/hypervisor-vsphere b/lib/nova_plugins/hypervisor-vsphere
index c406e09..698f836 100644
--- a/lib/nova_plugins/hypervisor-vsphere
+++ b/lib/nova_plugins/hypervisor-vsphere
@@ -42,9 +42,6 @@
     iniset $NOVA_CONF vmware host_username "$VMWAREAPI_USER"
     iniset $NOVA_CONF vmware host_password "$VMWAREAPI_PASSWORD"
     iniset_multiline $NOVA_CONF vmware cluster_name "$VMWAREAPI_CLUSTER"
-    if is_service_enabled neutron; then
-        iniset $NOVA_CONF vmware integration_bridge $OVS_BRIDGE
-    fi
 }
 
 # install_nova_hypervisor() - Install external components
diff --git a/lib/oslo b/lib/oslo
index 123572c..f64f327 100644
--- a/lib/oslo
+++ b/lib/oslo
@@ -59,7 +59,7 @@
     local name=$1
     if use_library_from_git "$name"; then
         git_clone_by_name "$name"
-        setup_lib "$name"
+        setup_dev_lib "$name"
     fi
 }
 
diff --git a/lib/swift b/lib/swift
index fc736a6..645bfd7 100644
--- a/lib/swift
+++ b/lib/swift
@@ -141,10 +141,6 @@
 # Toggle for deploying Swift under HTTPD + mod_wsgi
 SWIFT_USE_MOD_WSGI=${SWIFT_USE_MOD_WSGI:-False}
 
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,swift
-
-
 # Functions
 # ---------
 
@@ -455,6 +451,7 @@
 
 [filter:swift3]
 use = egg:swift3#swift3
+location = ${REGION_NAME}
 EOF
     fi
 
@@ -804,6 +801,7 @@
     OS_USERNAME=swift \
         OS_TENANT_NAME=$SERVICE_TENANT_NAME \
         OS_PASSWORD=$SERVICE_PASSWORD \
+        OS_AUTH_URL=$KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION \
         swift post -m "Temp-URL-Key: $SWIFT_TEMPURL_KEY"
 }
 
diff --git a/lib/tempest b/lib/tempest
index df0e382..f4d0a6d 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -398,6 +398,10 @@
     # neutron.allow_duplicate_networks option was removed from nova in Liberty
     # and is now the default behavior.
     iniset $TEMPEST_CONFIG compute-feature-enabled allow_duplicate_networks ${NOVA_ALLOW_DUPLICATE_NETWORKS:-True}
+    if is_service_enabled n-cell; then
+        # Cells doesn't support shelving/unshelving
+        iniset $TEMPEST_CONFIG compute-feature-enabled shelve False
+    fi
 
     # Network
     iniset $TEMPEST_CONFIG network api_version 2.0
@@ -426,7 +430,6 @@
     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
-    iniset $TEMPEST_CONFIG boto ssh_user ${DEFAULT_INSTANCE_USER:-cirros}
 
     # Orchestration Tests
     if is_service_enabled heat; then
@@ -455,9 +458,6 @@
     iniset $TEMPEST_CONFIG scenario large_ops_number ${TEMPEST_LARGE_OPS_NUMBER:-0}
 
     # Telemetry
-    # Ceilometer API optimization happened in Juno that allows to run more tests in tempest.
-    # Once Tempest retires support for icehouse this flag can be removed.
-    iniset $TEMPEST_CONFIG telemetry too_slow_to_test "False"
     iniset $TEMPEST_CONFIG telemetry-feature-enabled events "True"
 
     # Object Store
@@ -476,6 +476,8 @@
     # 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
 
     local volume_api_extensions=${VOLUME_API_EXTENSIONS:-"all"}
     if [[ ! -z "$DISABLE_VOLUME_API_EXTENSIONS" ]]; then
@@ -544,6 +546,11 @@
     fi
 
     # ``service_available``
+    #
+    # this tempest service list needs to be all the services that
+    # tempest supports, otherwise we can have an erroneous set of
+    # defaults (something defaulting true in Tempest, but not listed here).
+    TEMPEST_SERVICES="key,glance,nova,neutron,cinder,swift,heat,ceilometer,horizon,sahara,ironic,trove"
     for service in ${TEMPEST_SERVICES//,/ }; do
         if is_service_enabled $service ; then
             iniset $TEMPEST_CONFIG service_available $service "True"
@@ -554,7 +561,7 @@
 
     if is_ssl_enabled_service "key" || is_service_enabled tls-proxy; then
         # Use the ``BOTO_CONFIG`` environment variable to point to this file
-        iniset $BOTO_CONF Boto ca_certificates_file $SSL_BUNDLE_FILE
+        iniset -sudo $BOTO_CONF Boto ca_certificates_file $SSL_BUNDLE_FILE
         sudo chown $STACK_USER $BOTO_CONF
     fi
 
diff --git a/lib/zaqar b/lib/zaqar
deleted file mode 100644
index fdab3a2..0000000
--- a/lib/zaqar
+++ /dev/null
@@ -1,229 +0,0 @@
-#!/bin/bash
-#
-# lib/zaqar
-# Install and start **Zaqar** service
-
-# To enable a minimal set of Zaqar services, add the following to localrc:
-#
-#     enable_service zaqar-server
-#
-# Dependencies:
-# - functions
-# - OS_AUTH_URL for auth in api
-# - DEST set to the destination directory
-# - SERVICE_PASSWORD, SERVICE_TENANT_NAME for auth in api
-# - STACK_USER service user
-
-# stack.sh
-# ---------
-# install_zaqar
-# configure_zaqar
-# init_zaqar
-# start_zaqar
-# stop_zaqar
-# cleanup_zaqar
-# cleanup_zaqar_mongodb
-
-# Save trace setting
-XTRACE=$(set +o | grep xtrace)
-set +o xtrace
-
-
-# Defaults
-# --------
-
-# Set up default directories
-ZAQAR_DIR=$DEST/zaqar
-ZAQARCLIENT_DIR=$DEST/python-zaqarclient
-ZAQAR_CONF_DIR=/etc/zaqar
-ZAQAR_CONF=$ZAQAR_CONF_DIR/zaqar.conf
-ZAQAR_AUTH_CACHE_DIR=${ZAQAR_AUTH_CACHE_DIR:-/var/cache/zaqar}
-
-# Support potential entry-points console scripts
-ZAQAR_BIN_DIR=$(get_python_exec_prefix)
-
-# Set up database backend
-ZAQAR_BACKEND=${ZAQAR_BACKEND:-mongodb}
-
-
-# Set Zaqar repository
-ZAQAR_REPO=${ZAQAR_REPO:-${GIT_BASE}/openstack/zaqar.git}
-ZAQAR_BRANCH=${ZAQAR_BRANCH:-master}
-
-# Set client library repository
-ZAQARCLIENT_REPO=${ZAQARCLIENT_REPO:-${GIT_BASE}/openstack/python-zaqarclient.git}
-ZAQARCLIENT_BRANCH=${ZAQARCLIENT_BRANCH:-master}
-
-# Set Zaqar Connection Info
-ZAQAR_SERVICE_HOST=${ZAQAR_SERVICE_HOST:-$SERVICE_HOST}
-ZAQAR_SERVICE_PORT=${ZAQAR_SERVICE_PORT:-8888}
-ZAQAR_SERVICE_PROTOCOL=${ZAQAR_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
-
-# Tell Tempest this project is present
-TEMPEST_SERVICES+=,zaqar
-
-
-# Functions
-# ---------
-
-# Test if any Zaqar services are enabled
-# is_zaqar_enabled
-function is_zaqar_enabled {
-    [[ ,${ENABLED_SERVICES} =~ ,"zaqar-" ]] && return 0
-    return 1
-}
-
-# cleanup_zaqar() - Cleans up general things from previous
-# runs and storage specific left overs.
-function cleanup_zaqar {
-    if [ "$ZAQAR_BACKEND" = 'mongodb' ] ; then
-        cleanup_zaqar_mongodb
-    fi
-}
-
-# cleanup_zaqar_mongodb() - Remove residual data files, anything left over from previous
-# runs that a clean run would need to clean up
-function cleanup_zaqar_mongodb {
-    if ! timeout $SERVICE_TIMEOUT sh -c "while ! mongo zaqar --eval 'db.dropDatabase();'; do sleep 1; done"; then
-        die $LINENO "Mongo DB did not start"
-    else
-        full_version=$(mongo zaqar --eval 'db.dropDatabase();')
-        mongo_version=`echo $full_version | cut -d' ' -f4`
-        required_mongo_version='2.2'
-        if [[ $mongo_version < $required_mongo_version ]]; then
-            die $LINENO "Zaqar needs Mongo DB version >= 2.2 to run."
-        fi
-    fi
-}
-
-# configure_zaqarclient() - Set config files, create data dirs, etc
-function configure_zaqarclient {
-    setup_develop $ZAQARCLIENT_DIR
-}
-
-# configure_zaqar() - Set config files, create data dirs, etc
-function configure_zaqar {
-    setup_develop $ZAQAR_DIR
-
-    sudo install -d -o $STACK_USER -m 755 $ZAQAR_CONF_DIR
-
-    iniset $ZAQAR_CONF DEFAULT debug True
-    iniset $ZAQAR_CONF DEFAULT verbose True
-    iniset $ZAQAR_CONF DEFAULT admin_mode True
-    iniset $ZAQAR_CONF DEFAULT use_syslog $SYSLOG
-    iniset $ZAQAR_CONF 'drivers:transport:wsgi' bind $ZAQAR_SERVICE_HOST
-
-    configure_auth_token_middleware $ZAQAR_CONF zaqar $ZAQAR_AUTH_CACHE_DIR
-
-    if [ "$ZAQAR_BACKEND" = 'mysql' ] || [ "$ZAQAR_BACKEND" = 'postgresql' ] ; then
-        iniset $ZAQAR_CONF drivers storage sqlalchemy
-        iniset $ZAQAR_CONF 'drivers:storage:sqlalchemy' uri `database_connection_url zaqar`
-    elif [ "$ZAQAR_BACKEND" = 'mongodb' ] ; then
-        iniset $ZAQAR_CONF  drivers storage mongodb
-        iniset $ZAQAR_CONF 'drivers:storage:mongodb' uri mongodb://localhost:27017/zaqar
-        configure_mongodb
-    elif [ "$ZAQAR_BACKEND" = 'redis' ] ; then
-        iniset $ZAQAR_CONF  drivers storage redis
-        iniset $ZAQAR_CONF 'drivers:storage:redis' uri redis://localhost:6379
-        configure_redis
-    fi
-
-    iniset $ZAQAR_CONF DEFAULT notification_driver messaging
-    iniset $ZAQAR_CONF DEFAULT control_exchange zaqar
-
-    iniset_rpc_backend zaqar $ZAQAR_CONF
-
-    cleanup_zaqar
-}
-
-function configure_redis {
-    if is_ubuntu; then
-        install_package redis-server
-        pip_install_gr redis
-    elif is_fedora; then
-        install_package redis
-        pip_install_gr redis
-    else
-        exit_distro_not_supported "redis installation"
-    fi
-}
-
-function configure_mongodb {
-    # Set nssize to 2GB. This increases the number of namespaces supported
-    # # per database.
-    if is_ubuntu; then
-        sudo sed -i -e "
-            s|[^ \t]*#[ \t]*\(nssize[ \t]*=.*\$\)|\1|
-            s|^\(nssize[ \t]*=[ \t]*\).*\$|\1 2047|
-        " /etc/mongodb.conf
-        restart_service mongodb
-    elif is_fedora; then
-        sudo sed -i '/--nssize/!s/OPTIONS=\"/OPTIONS=\"--nssize 2047 /' /etc/sysconfig/mongod
-        restart_service mongod
-    fi
-}
-
-# init_zaqar() - Initialize etc.
-function init_zaqar {
-    # Create cache dir
-    sudo install -d -o $STACK_USER $ZAQAR_AUTH_CACHE_DIR
-    rm -f $ZAQAR_AUTH_CACHE_DIR/*
-}
-
-# install_zaqar() - Collect source and prepare
-function install_zaqar {
-    git_clone $ZAQAR_REPO $ZAQAR_DIR $ZAQAR_BRANCH
-    setup_develop $ZAQAR_DIR
-}
-
-# install_zaqarclient() - Collect source and prepare
-function install_zaqarclient {
-    git_clone $ZAQARCLIENT_REPO $ZAQARCLIENT_DIR $ZAQARCLIENT_BRANCH
-    setup_develop $ZAQARCLIENT_DIR
-}
-
-# start_zaqar() - Start running processes, including screen
-function start_zaqar {
-    if [[ "$USE_SCREEN" = "False" ]]; then
-        run_process zaqar-server "zaqar-server --config-file $ZAQAR_CONF --daemon"
-    else
-        run_process zaqar-server "zaqar-server --config-file $ZAQAR_CONF"
-    fi
-
-    echo "Waiting for Zaqar to start..."
-    if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- $ZAQAR_SERVICE_PROTOCOL://$ZAQAR_SERVICE_HOST:$ZAQAR_SERVICE_PORT/v1/health; do sleep 1; done"; then
-        die $LINENO "Zaqar did not start"
-    fi
-}
-
-# stop_zaqar() - Stop running processes
-function stop_zaqar {
-    local serv
-    # Kill the zaqar screen windows
-    for serv in zaqar-server; do
-        screen -S $SCREEN_NAME -p $serv -X kill
-    done
-}
-
-function create_zaqar_accounts {
-    create_service_user "zaqar"
-
-    if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
-
-        get_or_create_service "zaqar" "messaging" "Zaqar Service"
-        get_or_create_endpoint "messaging" \
-            "$REGION_NAME" \
-            "$ZAQAR_SERVICE_PROTOCOL://$ZAQAR_SERVICE_HOST:$ZAQAR_SERVICE_PORT" \
-            "$ZAQAR_SERVICE_PROTOCOL://$ZAQAR_SERVICE_HOST:$ZAQAR_SERVICE_PORT" \
-            "$ZAQAR_SERVICE_PROTOCOL://$ZAQAR_SERVICE_HOST:$ZAQAR_SERVICE_PORT"
-    fi
-
-}
-
-
-# Restore xtrace
-$XTRACE
-
-# Local variables:
-# mode: shell-script
-# End:
diff --git a/setup.cfg b/setup.cfg
index 5887134..e4b2888 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,7 @@
     README.md
 author = OpenStack
 author-email = openstack-dev@lists.openstack.org
-home-page = http://devstack.org
+home-page = http://docs.openstack.org/developer/devstack
 classifier =
     Intended Audience :: Developers
     License :: OSI Approved :: Apache Software License
diff --git a/stack.sh b/stack.sh
index accfd0a..cd8a11e 100755
--- a/stack.sh
+++ b/stack.sh
@@ -1,9 +1,8 @@
 #!/usr/bin/env bash
 
 # ``stack.sh`` is an opinionated OpenStack developer installation.  It
-# installs and configures various combinations of **Ceilometer**, **Cinder**,
-# **Glance**, **Heat**, **Horizon**, **Keystone**, **Nova**, **Neutron**,
-# and **Swift**
+# installs and configures various combinations of **Cinder**, **Glance**,
+# **Heat**, **Horizon**, **Keystone**, **Nova**, **Neutron**, and **Swift**
 
 # This script's options can be changed by setting appropriate environment
 # variables.  You can configure things like which git repositories to use,
@@ -28,13 +27,6 @@
 # Make sure custom grep options don't get in the way
 unset GREP_OPTIONS
 
-# Sanitize language settings to avoid commands bailing out
-# with "unsupported locale setting" errors.
-unset LANG
-unset LANGUAGE
-LC_ALL=C
-export LC_ALL
-
 # Make sure umask is sane
 umask 022
 
@@ -435,7 +427,7 @@
 
 # Set up logging of screen windows
 # Set ``SCREEN_LOGDIR`` to turn on logging of screen windows to the
-# directory specified in ``SCREEN_LOGDIR``, we will log to the the file
+# directory specified in ``SCREEN_LOGDIR``, we will log to the file
 # ``screen-$SERVICE_NAME-$TIMESTAMP.log`` in that dir and have a link
 # ``screen-$SERVICE_NAME.log`` to the latest log file.
 # Logs are kept for as long specified in ``LOGDAYS``.
@@ -522,7 +514,7 @@
 # Clone all external plugins
 fetch_plugins
 
-# Plugin Phase 0: override_defaults - allow pluggins to override
+# Plugin Phase 0: override_defaults - allow plugins to override
 # defaults before other services are run
 run_phase override_defaults
 
@@ -542,7 +534,6 @@
 source $TOP_DIR/lib/nova
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
-source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
@@ -826,13 +817,6 @@
     configure_horizon
 fi
 
-if is_service_enabled ceilometer; then
-    install_ceilometerclient
-    stack_install_service ceilometer
-    echo_summary "Configuring Ceilometer"
-    configure_ceilometer
-fi
-
 if is_service_enabled heat; then
     stack_install_service heat
     install_heat_other
@@ -1008,10 +992,6 @@
     create_cinder_accounts
     create_neutron_accounts
 
-    if is_service_enabled ceilometer; then
-        create_ceilometer_accounts
-    fi
-
     if is_service_enabled swift; then
         create_swift_accounts
     fi
@@ -1034,6 +1014,9 @@
     export OS_REGION_NAME=$REGION_NAME
 fi
 
+# Write a clouds.yaml file
+write_clouds_yaml
+
 # Horizon
 # -------
 
@@ -1183,8 +1166,6 @@
 # See https://help.ubuntu.com/community/CloudInit for more on ``cloud-init``
 
 if is_service_enabled g-reg; then
-    TOKEN=$(openstack token issue -c id -f value)
-    die_if_not_set $LINENO TOKEN "Keystone fail to get token"
 
     echo_summary "Uploading images"
 
@@ -1194,7 +1175,7 @@
     fi
 
     for image_url in ${IMAGE_URLS//,/ }; do
-        upload_image $image_url $TOKEN
+        upload_image $image_url
     done
 fi
 
@@ -1255,11 +1236,6 @@
     start_cinder
     create_volume_types
 fi
-if is_service_enabled ceilometer; then
-    echo_summary "Starting Ceilometer"
-    init_ceilometer
-    start_ceilometer
-fi
 
 # Configure and launch Heat engine, api and metadata
 if is_service_enabled heat; then
@@ -1300,43 +1276,6 @@
 # Save some values we generated for later use
 save_stackenv
 
-# Update/create user clouds.yaml file.
-# clouds.yaml will have
-# - A `devstack` entry for the `demo` user for the `demo` project.
-# - A `devstack-admin` entry for the `admin` user for the `admin` project.
-
-# The location is a variable to allow for easier refactoring later to make it
-# overridable. There is currently no usecase where doing so makes sense, so
-# it's not currently configurable.
-CLOUDS_YAML=~/.config/openstack/clouds.yaml
-
-mkdir -p $(dirname $CLOUDS_YAML)
-
-CA_CERT_ARG=''
-if [ -f "$SSL_BUNDLE_FILE" ]; then
-    CA_CERT_ARG="--os-cacert $SSL_BUNDLE_FILE"
-fi
-$TOP_DIR/tools/update_clouds_yaml.py \
-    --file $CLOUDS_YAML \
-    --os-cloud devstack \
-    --os-region-name $REGION_NAME \
-    --os-identity-api-version $IDENTITY_API_VERSION \
-    $CA_CERT_ARG \
-    --os-auth-url $KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION \
-    --os-username demo \
-    --os-password $ADMIN_PASSWORD \
-    --os-project-name demo
-$TOP_DIR/tools/update_clouds_yaml.py \
-    --file $CLOUDS_YAML \
-    --os-cloud devstack-admin \
-    --os-region-name $REGION_NAME \
-    --os-identity-api-version $IDENTITY_API_VERSION \
-    $CA_CERT_ARG \
-    --os-auth-url $KEYSTONE_AUTH_URI/v$IDENTITY_API_VERSION \
-    --os-username admin \
-    --os-password $ADMIN_PASSWORD \
-    --os-project-name admin
-
 
 # Wrapup configuration
 # ====================
@@ -1373,9 +1312,16 @@
     $TOP_DIR/local.sh
 fi
 
+# Sanity checks
+# =============
+
 # Check the status of running services
 service_check
 
+# ensure that all the libraries we think we installed from git,
+# actually were.
+check_libs_from_git
+
 
 # Bash completion
 # ===============
diff --git a/stackrc b/stackrc
index 156cb1f..c7c6313 100644
--- a/stackrc
+++ b/stackrc
@@ -2,6 +2,18 @@
 #
 # stackrc
 #
+
+# ensure we don't re-source this in the same environment
+[[ -z "$_DEVSTACK_STACKRC" ]] || return 0
+declare -r _DEVSTACK_STACKRC=1
+
+# Sanitize language settings to avoid commands bailing out
+# with "unsupported locale setting" errors.
+unset LANG
+unset LANGUAGE
+LC_ALL=C
+export LC_ALL
+
 # Find the other rc files
 RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd)
 
@@ -78,12 +90,6 @@
 # services will rely on the local toggle variable (e.g. ``KEYSTONE_USE_MOD_WSGI``)
 ENABLE_HTTPD_MOD_WSGI_SERVICES=True
 
-# Tell Tempest which services are available.  The default is set here as
-# Tempest falls late in the configuration sequence.  This differs from
-# ``ENABLED_SERVICES`` in that the project names are used here rather than
-# the service names, i.e.: ``TEMPEST_SERVICES="key,glance,nova"``
-TEMPEST_SERVICES=""
-
 # Set the default Nova APIs to enable
 NOVA_ENABLED_APIS=ec2,osapi_compute,metadata
 
@@ -182,10 +188,6 @@
 #
 ##############
 
-# telemetry service
-CEILOMETER_REPO=${CEILOMETER_REPO:-${GIT_BASE}/openstack/ceilometer.git}
-CEILOMETER_BRANCH=${CEILOMETER_BRANCH:-master}
-
 # block storage service
 CINDER_REPO=${CINDER_REPO:-${GIT_BASE}/openstack/cinder.git}
 CINDER_BRANCH=${CINDER_BRANCH:-master}
@@ -255,14 +257,10 @@
 
 ##############
 #
-#  OpenStack Client Library Componets
+#  OpenStack Client Library Components
 #
 ##############
 
-# ceilometer client library
-GITREPO["python-ceilometerclient"]=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git}
-GITBRANCH["python-ceilometerclient"]=${CEILOMETERCLIENT_BRANCH:-master}
-
 # volume client
 GITREPO["python-cinderclient"]=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
 GITBRANCH["python-cinderclient"]=${CINDERCLIENT_BRANCH:-master}
@@ -450,11 +448,16 @@
 # ceilometer middleware
 GITREPO["ceilometermiddleware"]=${CEILOMETERMIDDLEWARE_REPO:-${GIT_BASE}/openstack/ceilometermiddleware.git}
 GITBRANCH["ceilometermiddleware"]=${CEILOMETERMIDDLEWARE_BRANCH:-master}
+GITDIR["ceilometermiddleware"]=$DEST/ceilometermiddleware
 
 # os-brick library to manage local volume attaches
 GITREPO["os-brick"]=${OS_BRICK_REPO:-${GIT_BASE}/openstack/os-brick.git}
 GITBRANCH["os-brick"]=${OS_BRICK_BRANCH:-master}
 
+# ironic common lib
+GITREPO["ironic-lib"]=${IRONIC_LIB_REPO:-${GIT_BASE}/openstack/ironic-lib.git}
+GITBRANCH["ironic-lib"]=${IRONIC_LIB_BRANCH:-master}
+
 
 ##################
 #
@@ -560,40 +563,47 @@
 # Set default image based on ``VIRT_DRIVER`` and ``LIBVIRT_TYPE``, either of
 # which may be set in ``local.conf``.  Also allow ``DEFAULT_IMAGE_NAME`` and
 # ``IMAGE_URLS`` to be set in the `localrc` section of ``local.conf``.
-case "$VIRT_DRIVER" in
-    openvz)
-        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ubuntu-12.04-x86_64}
-        IMAGE_URLS=${IMAGE_URLS:-"http://download.openvz.org/template/precreated/ubuntu-12.04-x86_64.tar.gz"};;
-    libvirt)
-        case "$LIBVIRT_TYPE" in
-            lxc) # the cirros root disk in the uec tarball is empty, so it will not work for lxc
-                DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs}
-                IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs.img.gz"};;
-            *) # otherwise, use the uec style image (with kernel, ramdisk, disk)
-                DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
-                IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz"};;
-        esac
-        ;;
-    vsphere)
-        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.2-i386-disk.vmdk}
-        IMAGE_URLS=${IMAGE_URLS:-"http://partnerweb.vmware.com/programs/vmdkimage/cirros-0.3.2-i386-disk.vmdk"};;
-    xenserver)
-        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.4-x86_64-disk}
-        IMAGE_URLS=${IMAGE_URLS:-"http://ca.downloads.xensource.com/OpenStack/cirros-0.3.4-x86_64-disk.vhd.tgz"}
-        IMAGE_URLS+=",http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz";;
-    ironic)
-        # Ironic can do both partition and full disk images, depending on the driver
-        if [[ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]]; then
-            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-disk}
-        else
-            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-uec}
-        fi
-        IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz"}
-        IMAGE_URLS+=",http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-disk.img";;
-    *) # Default to Cirros with kernel, ramdisk and disk image
-        DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
-        IMAGE_URLS=${IMAGE_URLS:-"http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz"};;
-esac
+DOWNLOAD_DEFAULT_IMAGES=$(trueorfalse True DOWNLOAD_DEFAULT_IMAGES)
+if [[ "$DOWNLOAD_DEFAULT_IMAGES" == "True" ]]; then
+    if [[ -n "$IMAGE_URLS" ]]; then
+        IMAGE_URLS+=","
+    fi
+    case "$VIRT_DRIVER" in
+        openvz)
+            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-ubuntu-12.04-x86_64}
+            IMAGE_URLS+="http://download.openvz.org/template/precreated/ubuntu-12.04-x86_64.tar.gz";;
+        libvirt)
+            case "$LIBVIRT_TYPE" in
+                lxc) # the cirros root disk in the uec tarball is empty, so it will not work for lxc
+                    DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs}
+                    IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-rootfs.img.gz";;
+                *) # otherwise, use the uec style image (with kernel, ramdisk, disk)
+                    DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
+                    IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz";;
+                esac
+            ;;
+        vsphere)
+            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.2-i386-disk.vmdk}
+            IMAGE_URLS+="http://partnerweb.vmware.com/programs/vmdkimage/cirros-0.3.2-i386-disk.vmdk";;
+        xenserver)
+            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-0.3.4-x86_64-disk}
+            IMAGE_URLS+="http://ca.downloads.xensource.com/OpenStack/cirros-0.3.4-x86_64-disk.vhd.tgz"
+            IMAGE_URLS+=",http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz";;
+        ironic)
+            # Ironic can do both partition and full disk images, depending on the driver
+            if [[ "$IRONIC_DEPLOY_DRIVER" == "agent_ssh" ]]; then
+                DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-disk}
+            else
+                DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-x86_64-uec}
+            fi
+            IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz"
+            IMAGE_URLS+=",http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-disk.img";;
+        *) # Default to Cirros with kernel, ramdisk and disk image
+            DEFAULT_IMAGE_NAME=${DEFAULT_IMAGE_NAME:-cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec}
+            IMAGE_URLS+="http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-${CIRROS_ARCH}-uec.tar.gz";;
+    esac
+    DOWNLOAD_DEFAULT_IMAGES=False
+fi
 
 # Staging Area for New Images, have them here for at least 24hrs for nodepool
 # to cache them otherwise the failure rates in the gate are too high
@@ -606,6 +616,13 @@
     fi
 fi
 
+# Detect duplicate values in IMAGE_URLS
+for image_url in ${IMAGE_URLS//,/ }; do
+    if [ $(echo "$IMAGE_URLS" | grep -o -F "$image_url" | wc -l) -gt 1 ]; then
+        die $LINENO "$image_url is duplicate, please remove it from IMAGE_URLS."
+    fi
+done
+
 # 10Gb default volume backing file size
 VOLUME_BACKING_FILE_SIZE=${VOLUME_BACKING_FILE_SIZE:-10250M}
 
@@ -633,7 +650,12 @@
 # the memory used where there are a large number of CPUs present
 # (the default number of workers for many services is the number of CPUs)
 # Also sets the minimum number of workers to 2.
-API_WORKERS=${API_WORKERS:=$(( ($(nproc)/2)<2 ? 2 : ($(nproc)/2) ))}
+if [[ "$VIRT_DRIVER" = 'fake' ]]; then
+    # we need more workers for the large ops job
+    API_WORKERS=${API_WORKERS:=$(( ($(nproc)/2)<2 ? 2 : ($(nproc)/2) ))}
+else
+    API_WORKERS=${API_WORKERS:=$(( ($(nproc)/4)<2 ? 2 : ($(nproc)/4) ))}
+fi
 
 # Service startup timeout
 SERVICE_TIMEOUT=${SERVICE_TIMEOUT:-60}
diff --git a/tests/test_libs_from_pypi.sh b/tests/test_libs_from_pypi.sh
index d10cd0e..8e8c022 100755
--- a/tests/test_libs_from_pypi.sh
+++ b/tests/test_libs_from_pypi.sh
@@ -37,11 +37,11 @@
 ALL_LIBS+=" oslo.versionedobjects oslo.vmware keystonemiddleware"
 ALL_LIBS+=" oslo.serialization django_openstack_auth"
 ALL_LIBS+=" python-openstackclient oslo.rootwrap oslo.i18n"
-ALL_LIBS+=" python-ceilometerclient oslo.utils python-swiftclient"
+ALL_LIBS+=" oslo.utils python-swiftclient"
 ALL_LIBS+=" python-neutronclient tooz ceilometermiddleware oslo.policy"
 ALL_LIBS+=" debtcollector os-brick automaton futurist oslo.service"
 ALL_LIBS+=" oslo.cache oslo.reports"
-ALL_LIBS+=" keystoneauth"
+ALL_LIBS+=" keystoneauth ironic-lib"
 
 # Generate the above list with
 # echo ${!GITREPO[@]}
diff --git a/tools/create_userrc.sh b/tools/create_userrc.sh
index c2dbe1a..de44abb 100755
--- a/tools/create_userrc.sh
+++ b/tools/create_userrc.sh
@@ -158,12 +158,12 @@
 
 export -n SERVICE_TOKEN SERVICE_ENDPOINT OS_SERVICE_TOKEN OS_SERVICE_ENDPOINT
 
-EC2_URL=$(openstack endpoint show -f value -c publicurl ec2 || true)
+EC2_URL=$(openstack endpoint list --service ec2 --interface public --os-identity-api-version=3 -c URL -f value || true)
 if [[ -z $EC2_URL ]]; then
     EC2_URL=http://localhost:8773/
 fi
 
-S3_URL=$(openstack endpoint show -f value -c publicurl s3 || true)
+S3_URL=$(openstack endpoint list --service s3 --interface public --os-identity-api-version=3 -c URL -f value || true)
 if [[ -z $S3_URL ]]; then
     S3_URL=http://localhost:3333
 fi
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 4fff57f..a601cf2 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -134,6 +134,31 @@
             sudo systemctl start iptables
         fi
     fi
+
+    if  [[ "$os_RELEASE" -ge "21" ]]; 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
+        # maintainers keep things in sync, but since devstack takes
+        # over and installs later versions via pip we can end up with
+        # incompatible versions.
+        #
+        # The rpm package is not removed to preserve the dependent
+        # packages like cloud-init; rather we remove the symlinks and
+        # force a re-install of requests so the vendored versions it
+        # wants are present.
+        #
+        # Realted issues:
+        # https://bugs.launchpad.net/glance/+bug/1476770
+        # https://bugzilla.redhat.com/show_bug.cgi?id=1253823
+
+        base_path=/usr/lib/python2.7/site-packages/requests/packages
+        if [ -L $base_path/chardet -o -L $base_path/urllib3 ]; then
+            sudo rm -f /usr/lib/python2.7/site-packages/requests/packages/{chardet,urllib3}
+            # install requests with the bundled urllib3 to avoid conflicts
+            pip_install --upgrade --force-reinstall requests
+        fi
+    fi
 fi
 
 # The version of pip(1.5.4) supported by python-virtualenv(1.11.4) has
diff --git a/tools/make_cert.sh b/tools/make_cert.sh
index cb93e57..2628b40 100755
--- a/tools/make_cert.sh
+++ b/tools/make_cert.sh
@@ -5,7 +5,7 @@
 # Create a CA hierarchy (if necessary) and server certificate
 #
 # This mimics the CA structure that DevStack sets up when ``tls_proxy`` is enabled
-# but in the curent directory unless ``DATA_DIR`` is set
+# but in the current directory unless ``DATA_DIR`` is set
 
 ENABLE_TLS=True
 DATA_DIR=${DATA_DIR:-`pwd`/ca-data}
diff --git a/tools/xen/README.md b/tools/xen/README.md
index 61694e9..6212cc5 100644
--- a/tools/xen/README.md
+++ b/tools/xen/README.md
@@ -94,11 +94,6 @@
     XENAPI_CONNECTION_URL="http://address_of_your_xenserver"
     VNCSERVER_PROXYCLIENT_ADDRESS=address_of_your_xenserver
 
-    # Download a vhd and a uec image
-    IMAGE_URLS="\
-    https://github.com/downloads/citrix-openstack/warehouse/cirros-0.3.0-x86_64-disk.vhd.tgz,\
-    http://download.cirros-cloud.net/0.3.4/cirros-0.3.4-x86_64-uec.tar.gz"
-
     # Explicitly set virt driver
     VIRT_DRIVER=xenserver
 
diff --git a/tools/xen/functions b/tools/xen/functions
index 4e9fede..8c674dc 100644
--- a/tools/xen/functions
+++ b/tools/xen/functions
@@ -179,7 +179,8 @@
     local bridge_or_net_name
     bridge_or_net_name=$1
 
-    ifconfig $(bridge_for "$bridge_or_net_name") | grep "inet addr" | cut -d ":" -f2 | sed "s/ .*//"
+    ip -4 addr show $(bridge_for "$bridge_or_net_name") |\
+    awk '/inet/{split($2, ip, "/"); print ip[1];}'
 }
 
 function xenapi_is_listening_on {
diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh
index b49347e..e24d9ed 100755
--- a/tools/xen/install_os_domU.sh
+++ b/tools/xen/install_os_domU.sh
@@ -193,7 +193,10 @@
             TMP_DIR=/tmp/temp.$RANDOM
             mkdir -p $TMP_DIR
             mount -o loop $TOOLS_ISO $TMP_DIR
-            DEB_FILE=$(ls $TMP_DIR/Linux/*amd64.deb)
+            # the target deb package maybe *amd64.deb or *all.deb,
+            # so use *amd64.deb by default. If it doesn't exist,
+            # then use *all.deb.
+            DEB_FILE=$(ls $TMP_DIR/Linux/*amd64.deb || ls $TMP_DIR/Linux/*all.deb)
             cp $DEB_FILE $HTTP_SERVER_LOCATION
             umount $TMP_DIR
             rmdir $TMP_DIR
diff --git a/unstack.sh b/unstack.sh
index 10e5958..30447a7 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -45,7 +45,7 @@
 # Configure Projects
 # ==================
 
-# Plugin Phase 0: override_defaults - allow pluggins to override
+# Plugin Phase 0: override_defaults - allow plugins to override
 # defaults before other services are run
 run_phase override_defaults
 
@@ -65,7 +65,6 @@
 source $TOP_DIR/lib/nova
 source $TOP_DIR/lib/cinder
 source $TOP_DIR/lib/swift
-source $TOP_DIR/lib/ceilometer
 source $TOP_DIR/lib/heat
 source $TOP_DIR/lib/neutron-legacy
 source $TOP_DIR/lib/ldap
@@ -104,10 +103,6 @@
     stop_heat
 fi
 
-if is_service_enabled ceilometer; then
-    stop_ceilometer
-fi
-
 if is_service_enabled nova; then
     stop_nova
 fi