Merge "Configure region name in neutron & ceilometer config files"
diff --git a/HACKING.rst b/HACKING.rst
index 3ffe1e2..b7d9a49 100644
--- a/HACKING.rst
+++ b/HACKING.rst
@@ -110,8 +110,8 @@
 * Global configuration that may be referenced in ``local.conf``, i.e. ``DEST``, ``DATA_DIR``
 * Global service configuration like ``ENABLED_SERVICES``
 * Variables used by multiple services that do not have a clear owner, i.e.
-  ``VOLUME_BACKING_FILE_SIZE`` (nova-volumes and cinder) or ``PUBLIC_NETWORK_NAME``
-  (nova-network and neutron)
+  ``VOLUME_BACKING_FILE_SIZE`` (nova-compute, nova-volumes and cinder) or
+  ``PUBLIC_NETWORK_NAME`` (nova-network and neutron)
 * Variables that can not be cleanly declared in a project file due to
   dependency ordering, i.e. the order of sourcing the project files can
   not be changed for other reasons but the earlier file needs to dereference a
diff --git a/clean.sh b/clean.sh
index f2f1338..edbd04a 100755
--- a/clean.sh
+++ b/clean.sh
@@ -18,7 +18,7 @@
 FILES=$TOP_DIR/files
 
 # Load local configuration
-source $TOP_DIR/stackrc
+source $TOP_DIR/openrc
 
 # Get the variables that are set in stack.sh
 if [[ -r $TOP_DIR/.stackenv ]]; then
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index baebe97..fe3e2c2 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -200,22 +200,19 @@
 
         LOG_COLOR=False
 
-Logging the Screen Output
--------------------------
+Logging the Service Output
+--------------------------
 
-    | *Default: ``SCREEN_LOGDIR=""``*
-    |  By default DevStack runs the OpenStack services using ``screen``
-       which is useful for watching log and debug output. However, in
-       automated testing the interactive ``screen`` sessions may not be
-       available after the fact; setting ``SCREEN_LOGDIR`` enables logging
-       of the ``screen`` sessions in the specified directory. There will be
-       one file per ``screen`` session named for the session name and a
-       timestamp.
+    | *Default: ``LOGDIR=""``*
+    |  DevStack will log the stdout output of the services it starts.
+       When using ``screen`` this logs the output in the screen windows
+       to a file.  Without ``screen`` this simply redirects stdout of
+       the service process to a file in ``LOGDIR``.
     |
 
     ::
 
-        SCREEN_LOGDIR=$DEST/logs/screen
+        LOGDIR=$DEST/logs
 
     *Note the use of ``DEST`` to locate the main install directory; this
     is why we suggest setting it in ``local.conf``.*
@@ -352,19 +349,6 @@
         GLANCE_HOSTPORT=w.x.y.z:9292
         ENABLED_SERVICES=n-vol,n-cpu,n-net,n-api
 
-API rate limits
----------------
-
-    | Default: ``API_RATE_LIMIT=True``
-    | Integration tests such as Tempest will likely run afoul of the
-      default rate limits configured for Nova. Turn off rate limiting
-      during testing by setting ``API_RATE_LIMIT=False``.*
-    |
-
-    ::
-
-        API_RATE_LIMIT=False
-
 IP Version
     | Default: ``IP_VERSION=4``
     | This setting can be used to configure DevStack to create either an IPv4,
@@ -413,8 +397,8 @@
        FIXED_RANGE=10.254.1.0/24
        NETWORK_GATEWAY=10.254.1.1
        LOGDAYS=1
-       LOGFILE=$DEST/logs/stack.sh.log
-       SCREEN_LOGDIR=$DEST/logs/screen
+       LOGDIR=$DEST/logs
+       LOGFILE=$LOGDIR/stack.sh.log
        ADMIN_PASSWORD=quiet
        DATABASE_PASSWORD=$ADMIN_PASSWORD
        RABBIT_PASSWORD=$ADMIN_PASSWORD
diff --git a/doc/source/faq.rst b/doc/source/faq.rst
index 92d7945..f10c2ee 100644
--- a/doc/source/faq.rst
+++ b/doc/source/faq.rst
@@ -24,7 +24,7 @@
     by packaging in "real" deployments. To remove additional protections
     that will be desired/required in production would be a step
     backward.
-Q: But selinux is disabled in RHEL 6!
+Q: But selinux is disabled in RHEL!
     A: Today it is, yes. That is a specific exception that certain
     DevStack contributors fought strongly against. The primary reason it
     was allowed was to support using RHEL6 as the Python 2.6 test
@@ -70,11 +70,6 @@
 Q: Are there any differences between Ubuntu and Fedora support?
     A: Neutron is not fully supported prior to Fedora 18 due lack of
     OpenVSwitch packages.
-Q: How about RHEL 6?
-    A: RHEL 6 has Python 2.6 and many old modules packaged and is a
-    challenge to support. There are a number of specific RHEL6
-    work-arounds in ``stack.sh`` to handle this. But the testing on py26
-    is valuable so we do it...
 
 Operation and Configuration
 ===========================
diff --git a/doc/source/guides/neutron.rst b/doc/source/guides/neutron.rst
index 90d4ca3..95cde96 100644
--- a/doc/source/guides/neutron.rst
+++ b/doc/source/guides/neutron.rst
@@ -196,7 +196,7 @@
         SEGMENTATION_ID=2010
 
 In this configuration we are defining FIXED_RANGE to be a
-subnet that exists in the private RFC1918 address space - however in
+subnet that exists in the private RFC1918 address space - however
 in a real setup FIXED_RANGE would be a public IP address range, so
 that you could access your instances from the public internet.
 
diff --git a/extras.d/60-ceph.sh b/extras.d/60-ceph.sh
index 50bdfae..38b901b 100644
--- a/extras.d/60-ceph.sh
+++ b/extras.d/60-ceph.sh
@@ -6,14 +6,19 @@
         source $TOP_DIR/lib/ceph
     elif [[ "$1" == "stack" && "$2" == "pre-install" ]]; then
         echo_summary "Installing Ceph"
-        install_ceph
-        echo_summary "Configuring Ceph"
-        configure_ceph
-        # NOTE (leseb): Do everything here because we need to have Ceph started before the main
-        # OpenStack components. Ceph OSD must start here otherwise we can't upload any images.
-        echo_summary "Initializing Ceph"
-        init_ceph
-        start_ceph
+        check_os_support_ceph
+        if [ "$REMOTE_CEPH" = "False" ]; then
+            install_ceph
+            echo_summary "Configuring Ceph"
+            configure_ceph
+            # NOTE (leseb): Do everything here because we need to have Ceph started before the main
+            # OpenStack components. Ceph OSD must start here otherwise we can't upload any images.
+            echo_summary "Initializing Ceph"
+            init_ceph
+            start_ceph
+        else
+            install_ceph_remote
+        fi
     elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
         if is_service_enabled glance; then
             echo_summary "Configuring Glance for Ceph"
@@ -32,14 +37,39 @@
             echo_summary "Configuring libvirt secret"
             import_libvirt_secret_ceph
         fi
+
+        if [ "$REMOTE_CEPH" = "False" ]; then
+            if is_service_enabled glance; then
+                echo_summary "Configuring Glance for Ceph"
+                configure_ceph_embedded_glance
+            fi
+            if is_service_enabled nova; then
+                echo_summary "Configuring Nova for Ceph"
+                configure_ceph_embedded_nova
+            fi
+            if is_service_enabled cinder; then
+                echo_summary "Configuring Cinder for Ceph"
+                configure_ceph_embedded_cinder
+            fi
+        fi
     fi
 
     if [[ "$1" == "unstack" ]]; then
-        stop_ceph
-        cleanup_ceph
+        if [ "$REMOTE_CEPH" = "True" ]; then
+            cleanup_ceph_remote
+        else
+            cleanup_ceph_embedded
+            stop_ceph
+        fi
+        cleanup_ceph_general
     fi
 
     if [[ "$1" == "clean" ]]; then
-        cleanup_ceph
+        if [ "$REMOTE_CEPH" = "True" ]; then
+            cleanup_ceph_remote
+        else
+            cleanup_ceph_embedded
+        fi
+        cleanup_ceph_general
     fi
 fi
diff --git a/extras.d/70-sahara.sh b/extras.d/70-sahara.sh
index 2a34999..f177766 100644
--- a/extras.d/70-sahara.sh
+++ b/extras.d/70-sahara.sh
@@ -15,6 +15,7 @@
         create_sahara_accounts
     elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
         echo_summary "Initializing sahara"
+        sahara_register_images
         start_sahara
     fi
 
diff --git a/extras.d/70-tuskar.sh b/extras.d/70-tuskar.sh
index e77c504..6e26db2 100644
--- a/extras.d/70-tuskar.sh
+++ b/extras.d/70-tuskar.sh
@@ -65,7 +65,7 @@
 TUSKAR_DIR=$DEST/tuskar
 TUSKARCLIENT_DIR=$DEST/python-tuskarclient
 TUSKAR_AUTH_CACHE_DIR=${TUSKAR_AUTH_CACHE_DIR:-/var/cache/tuskar}
-TUSKAR_STANDALONE=`trueorfalse False $TUSKAR_STANDALONE`
+TUSKAR_STANDALONE=$(trueorfalse False TUSKAR_STANDALONE)
 TUSKAR_CONF_DIR=/etc/tuskar
 TUSKAR_CONF=$TUSKAR_CONF_DIR/tuskar.conf
 TUSKAR_API_HOST=${TUSKAR_API_HOST:-$HOST_IP}
@@ -131,7 +131,7 @@
 function init_tuskar {
 
     # (re)create tuskar database
-    recreate_database tuskar utf8
+    recreate_database tuskar
 
     tuskar-dbsync --config-file $TUSKAR_CONF
     create_tuskar_cache_dir
diff --git a/files/apache-keystone.template b/files/apache-keystone.template
index 2190d83..504dc01 100644
--- a/files/apache-keystone.template
+++ b/files/apache-keystone.template
@@ -32,7 +32,3 @@
     %SSLCERTFILE%
     %SSLKEYFILE%
 </VirtualHost>
-
-# Workaround for missing path on RHEL6, see
-#  https://bugzilla.redhat.com/show_bug.cgi?id=1121019
-WSGISocketPrefix /var/run/%APACHE_NAME%
diff --git a/files/debs/glance b/files/debs/glance
index 15e09aa..8db8145 100644
--- a/files/debs/glance
+++ b/files/debs/glance
@@ -7,7 +7,6 @@
 python-routes
 python-greenlet
 python-sqlalchemy
-python-wsgiref
 python-pastedeploy
 python-xattr
 python-iso8601
diff --git a/files/debs/neutron b/files/debs/neutron
index fd99677..5a59b22 100644
--- a/files/debs/neutron
+++ b/files/debs/neutron
@@ -1,3 +1,4 @@
+acl     # testonly
 ebtables
 iptables
 iputils-ping
diff --git a/files/patches/unittest2-discover.patch b/files/patches/unittest2-discover.patch
deleted file mode 100644
index 347300d..0000000
--- a/files/patches/unittest2-discover.patch
+++ /dev/null
@@ -1,16 +0,0 @@
-diff -r b2efb7df637b discover.py
---- a/discover.py	Thu Mar 24 00:31:02 2011 -0400
-+++ b/discover.py	Thu Nov 28 12:02:19 2013 +0000
-@@ -82,7 +82,11 @@
-     """
-     testMethodPrefix = 'test'
-     sortTestMethodsUsing = cmp
--    suiteClass = unittest.TestSuite
-+    try:
-+        import unittest2
-+        suiteClass = unittest2.TestSuite
-+    except ImportError:
-+        suiteClass = unittest.TestSuite
-     _top_level_dir = None
- 
-     def loadTestsFromTestCase(self, testCaseClass):
diff --git a/files/rpms-suse/glance b/files/rpms-suse/glance
index edd1564..9b962f9 100644
--- a/files/rpms-suse/glance
+++ b/files/rpms-suse/glance
@@ -8,5 +8,4 @@
 python-greenlet
 python-iso8601
 python-pyOpenSSL
-python-wsgiref
 python-xattr
diff --git a/files/rpms-suse/neutron b/files/rpms-suse/neutron
index 8431bd1..50ee145 100644
--- a/files/rpms-suse/neutron
+++ b/files/rpms-suse/neutron
@@ -1,3 +1,4 @@
+acl     # testonly
 dnsmasq
 dnsmasq-utils # dist:opensuse-12.3,opensuse-13.1
 ebtables
diff --git a/files/rpms/cinder b/files/rpms/cinder
index eedff18..082a35a 100644
--- a/files/rpms/cinder
+++ b/files/rpms/cinder
@@ -3,4 +3,4 @@
 qemu-img
 postgresql-devel
 iscsi-initiator-utils
-python-lxml         #dist:f19,f20,f21,rhel7
+python-lxml
diff --git a/files/rpms/general b/files/rpms/general
index ee7cc12..13c8a87 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -13,7 +13,6 @@
 libxslt-devel
 psmisc
 pylint
-python-prettytable # dist:rhel6 [1]
 python-unittest2
 python-virtualenv
 python-devel
@@ -27,8 +26,3 @@
 libyaml-devel
 gettext  # used for compiling message catalogs
 net-tools
-
-# [1] : some of installed tools have unversioned dependencies on this,
-# but others have versioned (<=0.7).  So if a later version (0.7.1)
-# gets installed in response to an unversioned dependency, it breaks.
-# This pre-installs a compatible 0.6(ish) version from RHEL
diff --git a/files/rpms/glance b/files/rpms/glance
index d2792cf..a09b669 100644
--- a/files/rpms/glance
+++ b/files/rpms/glance
@@ -6,10 +6,9 @@
 python-argparse
 python-eventlet
 python-greenlet
-python-lxml         #dist:f19,f20,f21,rhel7
-python-paste-deploy #dist:f19,f20,f21,rhel7
+python-lxml
+python-paste-deploy
 python-routes
 python-sqlalchemy
-python-wsgiref      #dist:f18,f19,f20,f21
 pyxattr
 zlib-devel          # testonly
diff --git a/files/rpms/horizon b/files/rpms/horizon
index 82385ed..585c36c 100644
--- a/files/rpms/horizon
+++ b/files/rpms/horizon
@@ -12,8 +12,8 @@
 python-migrate
 python-mox
 python-nose
-python-paste        #dist:f19,f20,f21
-python-paste-deploy #dist:f19,f20,f21
+python-paste
+python-paste-deploy
 python-routes
 python-sqlalchemy
 python-webob
diff --git a/files/rpms/keystone b/files/rpms/keystone
index 8b0953d..45492e0 100644
--- a/files/rpms/keystone
+++ b/files/rpms/keystone
@@ -1,10 +1,10 @@
 MySQL-python
 python-greenlet
-libxslt-devel       # dist:f20,f21
-python-lxml         #dist:f19,f20,f21
-python-paste        #dist:f19,f20,f21
-python-paste-deploy #dist:f19,f20,f21
-python-paste-script #dist:f19,f20,f21
+libxslt-devel
+python-lxml
+python-paste
+python-paste-deploy
+python-paste-script
 python-routes
 python-sqlalchemy
 python-webob
diff --git a/files/rpms/neutron b/files/rpms/neutron
index f2473fb..59152d6 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -1,4 +1,5 @@
 MySQL-python
+acl     # testonly
 dnsmasq # for q-dhcp
 dnsmasq-utils # for dhcp_release
 ebtables
@@ -11,9 +12,8 @@
 python-eventlet
 python-greenlet
 python-iso8601
-#rhel6 gets via pip
-python-paste        # dist:f19,f20,f21,rhel7
-python-paste-deploy # dist:f19,f20,f21,rhel7
+python-paste
+python-paste-deploy
 python-qpid # NOPRIME
 python-routes
 python-sqlalchemy
diff --git a/files/rpms/nova b/files/rpms/nova
index 07f13c7..557de90 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -29,11 +29,9 @@
 python-lockfile
 python-migrate
 python-mox
-python-paramiko # dist:f19,f20,f21,rhel7
-# ^ on RHEL6, brings in python-crypto which conflicts with version from
-# pip we need
-python-paste        # dist:f19,f20,f21,rhel7
-python-paste-deploy # dist:f19,f20,f21,rhel7
+python-paramiko
+python-paste
+python-paste-deploy
 python-qpid # NOPRIME
 python-routes
 python-sqlalchemy
diff --git a/files/rpms/swift b/files/rpms/swift
index ccda22b..0fcdb0f 100644
--- a/files/rpms/swift
+++ b/files/rpms/swift
@@ -6,7 +6,7 @@
 python-greenlet
 python-netifaces
 python-nose
-python-paste-deploy # dist:f19,f20,f21,rhel7
+python-paste-deploy
 python-simplejson
 python-webob
 pyxattr
diff --git a/functions b/functions
index c7a3b9d..5b3a8ea 100644
--- a/functions
+++ b/functions
@@ -42,7 +42,7 @@
     if [[ $image_url != file* ]]; then
         # Downloads the image (uec ami+akistyle), then extracts it.
         if [[ ! -f $FILES/$image_fname || "$(stat -c "%s" $FILES/$image_fname)" = "0" ]]; then
-            wget -c $image_url -O $FILES/$image_fname
+            wget --progress=dot:giga -c $image_url -O $FILES/$image_fname
             if [[ $? -ne 0 ]]; then
                 echo "Not found: $image_url"
                 return
@@ -116,7 +116,7 @@
             if [[ $flat_url != file* ]]; then
                 if [[ ! -f $FILES/$flat_fname || \
                 "$(stat -c "%s" $FILES/$flat_fname)" = "0" ]]; then
-                    wget -c $flat_url -O $FILES/$flat_fname
+                    wget --progress=dot:giga -c $flat_url -O $FILES/$flat_fname
                 fi
                 image="$FILES/${flat_fname}"
             else
@@ -353,7 +353,7 @@
     local boot_timeout=$3
     local expected=${4:-"True"}
     local check_command=""
-    MULTI_HOST=`trueorfalse False $MULTI_HOST`
+    MULTI_HOST=$(trueorfalse False MULTI_HOST)
     if [[ "$MULTI_HOST" = "True" && "$from_net" = "$PRIVATE_NETWORK_NAME" ]]; then
         return
     fi
diff --git a/functions-common b/functions-common
index 7a6c3a1..4d1c89a 100644
--- a/functions-common
+++ b/functions-common
@@ -21,12 +21,10 @@
 #
 # The following variables are assumed to be defined by certain functions:
 #
-# - ``GIT_DEPTH``
 # - ``ENABLED_SERVICES``
 # - ``ERROR_ON_CLONE``
 # - ``FILES``
 # - ``OFFLINE``
-# - ``PIP_DOWNLOAD_CACHE``
 # - ``RECLONE``
 # - ``REQUIREMENTS_DIR``
 # - ``STACK_USER``
@@ -44,6 +42,8 @@
 declare -A GITBRANCH
 declare -A GITDIR
 
+TRACK_DEPENDS=${TRACK_DEPENDS:-False}
+
 # Config Functions
 # ================
 
@@ -244,7 +244,8 @@
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
     local default=$1
-    local testval=$2
+    local literal=$2
+    local testval=${!literal}
 
     [[ -z "$testval" ]] && { echo "$default"; return; }
     [[ "0 no No NO false False FALSE" =~ "$testval" ]] && { echo "False"; return; }
@@ -253,6 +254,14 @@
     $xtrace
 }
 
+function isset {
+    nounset=$(set +o | grep nounset)
+    set +o nounset
+    [[ -n "${!1+x}" ]]
+    result=$?
+    $nounset
+    return $result
+}
 
 # Control Functions
 # =================
@@ -310,8 +319,8 @@
     set +o xtrace
     local msg="[ERROR] ${BASH_SOURCE[2]}:$1 $2"
     echo $msg 1>&2;
-    if [[ -n ${SCREEN_LOGDIR} ]]; then
-        echo $msg >> "${SCREEN_LOGDIR}/error.log"
+    if [[ -n ${LOGDIR} ]]; then
+        echo $msg >> "${LOGDIR}/error.log"
     fi
     $xtrace
     return $exitcode
@@ -363,8 +372,8 @@
     set +o xtrace
     local msg="[WARNING] ${BASH_SOURCE[2]}:$1 $2"
     echo $msg 1>&2;
-    if [[ -n ${SCREEN_LOGDIR} ]]; then
-        echo $msg >> "${SCREEN_LOGDIR}/error.log"
+    if [[ -n ${LOGDIR} ]]; then
+        echo $msg >> "${LOGDIR}/error.log"
     fi
     $xtrace
     return $exitcode
@@ -382,7 +391,11 @@
 # ``os_UPDATE`` - update: ex. the ``5`` in ``RHEL6.5``
 # ``os_PACKAGE`` - package type: ``deb`` or ``rpm``
 # ``os_CODENAME`` - vendor's codename for release: ``snow leopard``, ``trusty``
-declare os_VENDOR os_RELEASE os_UPDATE os_PACKAGE os_CODENAME
+os_VENDOR=""
+os_RELEASE=""
+os_UPDATE=""
+os_PACKAGE=""
+os_CODENAME=""
 
 # GetOSVersion
 function GetOSVersion {
@@ -578,8 +591,7 @@
 # Set global ``RECLONE=yes`` to simulate a clone when dest-dir exists
 # Set global ``ERROR_ON_CLONE=True`` to abort execution with an error if the git repo
 # does not exist (default is False, meaning the repo will be cloned).
-# Set global ``GIT_DEPTH=<number>`` to limit the history depth of the git clone
-# Uses globals ``ERROR_ON_CLONE``, ``OFFLINE``, ``RECLONE``, ``GIT_DEPTH``
+# Uses globals ``ERROR_ON_CLONE``, ``OFFLINE``, ``RECLONE``
 # git_clone remote dest-dir branch
 function git_clone {
     local git_remote=$1
@@ -588,9 +600,8 @@
     local orig_dir=$(pwd)
     local git_clone_flags=""
 
-    RECLONE=$(trueorfalse False $RECLONE)
-
-    if [[ -n "${GIT_DEPTH}" ]]; then
+    RECLONE=$(trueorfalse False RECLONE)
+    if [[ "${GIT_DEPTH}" -gt 0 ]]; then
         git_clone_flags="$git_clone_flags --depth $GIT_DEPTH"
     fi
 
@@ -815,7 +826,7 @@
 # Gets or creates a domain
 # Usage: get_or_create_domain <name> <description>
 function get_or_create_domain {
-    local os_url="$KEYSTONE_SERVICE_URI/v3"
+    local os_url="$KEYSTONE_SERVICE_URI_V3"
     # Gets domain id
     local domain_id=$(
         # Gets domain id
@@ -831,6 +842,23 @@
     echo $domain_id
 }
 
+# Gets or creates group
+# Usage: get_or_create_group <groupname> [<domain> <description>]
+function get_or_create_group {
+    local domain=${2:+--domain ${2}}
+    local desc="${3:-}"
+    local os_url="$KEYSTONE_SERVICE_URI_V3"
+    # Gets group id
+    local group_id=$(
+        # Creates new group with --or-show
+        openstack --os-token=$OS_TOKEN --os-url=$os_url \
+            --os-identity-api-version=3 group create $1 \
+            $domain --description "$desc" --or-show \
+            -f value -c id
+    )
+    echo $group_id
+}
+
 # Gets or creates user
 # Usage: get_or_create_user <username> <password> <project> [<email> [<domain>]]
 function get_or_create_user {
@@ -843,7 +871,7 @@
     local domain=""
     if [[ ! -z "$5" ]]; then
         domain="--domain=$5"
-        os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI/v3 --os-identity-api-version=3"
+        os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI_V3 --os-identity-api-version=3"
     fi
     # Gets user id
     local user_id=$(
@@ -868,7 +896,7 @@
     local domain=""
     if [[ ! -z "$2" ]]; then
         domain="--domain=$2"
-        os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI/v3 --os-identity-api-version=3"
+        os_cmd="$os_cmd --os-url=$KEYSTONE_SERVICE_URI_V3 --os-identity-api-version=3"
     fi
     local project_id=$(
         # Creates new project with --or-show
@@ -891,8 +919,8 @@
 # Usage: get_or_add_user_role <role> <user> <project>
 function get_or_add_user_role {
     # Gets user role id
-    local user_role_id=$(openstack user role list \
-        $2 \
+    local user_role_id=$(openstack role list \
+        --user $2 \
         --project $3 \
         --column "ID" \
         --column "Name" \
@@ -917,8 +945,8 @@
         openstack service show $1 -f value -c id 2>/dev/null ||
         # Creates new service if not exists
         openstack service create \
-            $1 \
-            --type=$2 \
+            $2 \
+            --name $1 \
             --description="$3" \
             -f value -c id
     )
@@ -979,9 +1007,10 @@
     [[ "$(id -u)" = "0" ]] && sudo="env"
 
     $xtrace
+
     $sudo DEBIAN_FRONTEND=noninteractive \
-        http_proxy=$http_proxy https_proxy=$https_proxy \
-        no_proxy=$no_proxy \
+        http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} \
+        no_proxy=${no_proxy:-} \
         apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
 }
 
@@ -1000,10 +1029,10 @@
     set +o xtrace
     local services=$@
     local package_dir=$(_get_package_dir)
-    local file_to_parse
-    local service
+    local file_to_parse=""
+    local service=""
 
-    INSTALL_TESTONLY_PACKAGES=$(trueorfalse False $INSTALL_TESTONLY_PACKAGES)
+    INSTALL_TESTONLY_PACKAGES=$(trueorfalse False INSTALL_TESTONLY_PACKAGES)
 
     if [[ -z "$package_dir" ]]; then
         echo "No package directory supplied"
@@ -1011,7 +1040,6 @@
     fi
     if [[ -z "$DISTRO" ]]; then
         GetDistro
-        echo "Found Distro $DISTRO"
     fi
     for service in ${services//,/ }; do
         # Allow individual services to specify dependencies
@@ -1114,6 +1142,10 @@
 # Uses globals ``NO_UPDATE_REPOS``, ``REPOS_UPDATED``, ``RETRY_UPDATE``
 # install_package package [package ...]
 function update_package_repo {
+    NO_UPDATE_REPOS=${NO_UPDATE_REPOS:-False}
+    REPOS_UPDATED=${REPOS_UPDATED:-False}
+    RETRY_UPDATE=${RETRY_UPDATE:-False}
+
     if [[ "$NO_UPDATE_REPOS" = "True" ]]; then
         return 0
     fi
@@ -1229,8 +1261,8 @@
 # _run_process() is designed to be backgrounded by run_process() to simulate a
 # fork.  It includes the dirty work of closing extra filehandles and preparing log
 # files to produce the same logs as screen_it().  The log filename is derived
-# from the service name and global-and-now-misnamed ``SCREEN_LOGDIR``
-# Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
+# from the service name.
+# Uses globals ``CURRENT_LOG_TIME``, ``LOGDIR``, ``SCREEN_LOGDIR``, ``SCREEN_NAME``, ``SERVICE_DIR``
 # If an optional group is provided sg will be used to set the group of
 # the command.
 # _run_process service "command-line" [group]
@@ -1245,9 +1277,14 @@
     exec 3>&-
     exec 6>&-
 
-    if [[ -n ${SCREEN_LOGDIR} ]]; then
-        exec 1>&${SCREEN_LOGDIR}/screen-${service}.${CURRENT_LOG_TIME}.log 2>&1
-        ln -sf ${SCREEN_LOGDIR}/screen-${service}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${service}.log
+    local real_logfile="${LOGDIR}/${service}.log.${CURRENT_LOG_TIME}"
+    if [[ -n ${LOGDIR} ]]; then
+        exec 1>&"$real_logfile" 2>&1
+        ln -sf "$real_logfile" ${LOGDIR}/${service}.log
+        if [[ -n ${SCREEN_LOGDIR} ]]; then
+            # Drop the backward-compat symlink
+            ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${service}.log
+        fi
 
         # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
         export PYTHONUNBUFFERED=1
@@ -1311,7 +1348,7 @@
 }
 
 # Helper to launch a process in a named screen
-# Uses globals ``CURRENT_LOG_TIME``, ``SCREEN_NAME``, ``SCREEN_LOGDIR``,
+# Uses globals ``CURRENT_LOG_TIME``, ```LOGDIR``, ``SCREEN_LOGDIR``, `SCREEN_NAME``,
 # ``SERVICE_DIR``, ``USE_SCREEN``
 # screen_process name "command-line" [group]
 # Run a command in a shell in a screen window, if an optional group
@@ -1323,17 +1360,25 @@
 
     SCREEN_NAME=${SCREEN_NAME:-stack}
     SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
-    USE_SCREEN=$(trueorfalse True $USE_SCREEN)
+    USE_SCREEN=$(trueorfalse True USE_SCREEN)
 
     # Append the process to the screen rc file
     screen_rc "$name" "$command"
 
     screen -S $SCREEN_NAME -X screen -t $name
 
-    if [[ -n ${SCREEN_LOGDIR} ]]; then
-        screen -S $SCREEN_NAME -p $name -X logfile ${SCREEN_LOGDIR}/screen-${name}.${CURRENT_LOG_TIME}.log
+    local real_logfile="${LOGDIR}/${name}.log.${CURRENT_LOG_TIME}"
+    echo "LOGDIR: $LOGDIR"
+    echo "SCREEN_LOGDIR: $SCREEN_LOGDIR"
+    echo "log: $real_logfile"
+    if [[ -n ${LOGDIR} ]]; then
+        screen -S $SCREEN_NAME -p $name -X logfile "$real_logfile"
         screen -S $SCREEN_NAME -p $name -X log on
-        ln -sf ${SCREEN_LOGDIR}/screen-${name}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${name}.log
+        ln -sf "$real_logfile" ${LOGDIR}/${name}.log
+        if [[ -n ${SCREEN_LOGDIR} ]]; then
+            # Drop the backward-compat symlink
+            ln -sf "$real_logfile" ${SCREEN_LOGDIR}/screen-${1}.log
+        fi
     fi
 
     # sleep to allow bash to be ready to be send the command - we are
@@ -1378,8 +1423,8 @@
         echo "screen -t $1 bash" >> $SCREENRC
         echo "stuff \"$2$NL\"" >> $SCREENRC
 
-        if [[ -n ${SCREEN_LOGDIR} ]]; then
-            echo "logfile ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log" >>$SCREENRC
+        if [[ -n ${LOGDIR} ]]; then
+            echo "logfile ${LOGDIR}/${1}.log.${CURRENT_LOG_TIME}" >>$SCREENRC
             echo "log on" >>$SCREENRC
         fi
     fi
@@ -1396,7 +1441,7 @@
 
     SCREEN_NAME=${SCREEN_NAME:-stack}
     SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
-    USE_SCREEN=$(trueorfalse True $USE_SCREEN)
+    USE_SCREEN=$(trueorfalse True USE_SCREEN)
 
     if is_service_enabled $service; then
         # Clean up the screen window
@@ -1414,7 +1459,7 @@
     local service=$1
 
     SERVICE_DIR=${SERVICE_DIR:-${DEST}/status}
-    USE_SCREEN=$(trueorfalse True $USE_SCREEN)
+    USE_SCREEN=$(trueorfalse True USE_SCREEN)
 
     if is_service_enabled $service; then
         # Kill via pid if we have one available
@@ -1464,7 +1509,7 @@
     local name=$1
     local logfile=$2
 
-    USE_SCREEN=$(trueorfalse True $USE_SCREEN)
+    USE_SCREEN=$(trueorfalse True USE_SCREEN)
     if [[ "$USE_SCREEN" = "True" ]]; then
         screen_process "$name" "sudo tail -f $logfile"
     fi
@@ -1491,8 +1536,8 @@
     exec 6>&-
 
     if [[ -n ${SCREEN_LOGDIR} ]]; then
-        exec 1>&${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log 2>&1
-        ln -sf ${SCREEN_LOGDIR}/screen-${1}.${CURRENT_LOG_TIME}.log ${SCREEN_LOGDIR}/screen-${1}.log
+        exec 1>&${SCREEN_LOGDIR}/screen-${1}.log.${CURRENT_LOG_TIME} 2>&1
+        ln -sf ${SCREEN_LOGDIR}/screen-${1}.log.${CURRENT_LOG_TIME} ${SCREEN_LOGDIR}/screen-${1}.log
 
         # TODO(dtroyer): Hack to get stdout from the Python interpreter for the logs.
         export PYTHONUNBUFFERED=1
@@ -1569,13 +1614,13 @@
 }
 
 # Wrapper for ``pip install`` to set cache and proxy environment variables
-# Uses globals ``OFFLINE``, ``PIP_DOWNLOAD_CACHE``,
-# ``TRACK_DEPENDS``, ``*_proxy``
+# Uses globals ``OFFLINE``, ``TRACK_DEPENDS``, ``*_proxy``
 # pip_install package [package ...]
 function pip_install {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
-    if [[ "$OFFLINE" = "True" || -z "$@" ]]; then
+    local offline=${OFFLINE:-False}
+    if [[ "$offline" == "True" || -z "$@" ]]; then
         $xtrace
         return
     fi
@@ -1595,22 +1640,29 @@
         local sudo_pip="sudo -H"
     fi
 
+    local pip_version=$(python -c "import pip; \
+                        print(pip.__version__.strip('.')[0])")
+    if (( pip_version<6 )); then
+        die $LINENO "Currently installed pip version ${pip_version} does not" \
+            "meet minimum requirements (>=6)."
+    fi
+
     $xtrace
-    $sudo_pip PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \
-        http_proxy=$http_proxy \
-        https_proxy=$https_proxy \
-        no_proxy=$no_proxy \
+    $sudo_pip \
+        http_proxy=${http_proxy:-} \
+        https_proxy=${https_proxy:-} \
+        no_proxy=${no_proxy:-} \
         $cmd_pip install \
         $@
 
-    INSTALL_TESTONLY_PACKAGES=$(trueorfalse False $INSTALL_TESTONLY_PACKAGES)
+    INSTALL_TESTONLY_PACKAGES=$(trueorfalse False INSTALL_TESTONLY_PACKAGES)
     if [[ "$INSTALL_TESTONLY_PACKAGES" == "True" ]]; then
         local test_req="$@/test-requirements.txt"
         if [[ -e "$test_req" ]]; then
-            $sudo_pip PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \
-                http_proxy=$http_proxy \
-                https_proxy=$https_proxy \
-                no_proxy=$no_proxy \
+            $sudo_pip \
+                http_proxy=${http_proxy:-} \
+                https_proxy=${https_proxy:-} \
+                no_proxy=${no_proxy:-} \
                 $cmd_pip install \
                 -r $test_req
         fi
@@ -2080,13 +2132,13 @@
 #     http_proxy=http://proxy.example.com:3128/ no_proxy=repo.example.net ./stack.sh
 
 function export_proxy_variables {
-    if [[ -n "$http_proxy" ]]; then
+    if isset http_proxy ; then
         export http_proxy=$http_proxy
     fi
-    if [[ -n "$https_proxy" ]]; then
+    if isset https_proxy ; then
         export https_proxy=$https_proxy
     fi
-    if [[ -n "$no_proxy" ]]; then
+    if isset no_proxy ; then
         export no_proxy=$no_proxy
     fi
 }
diff --git a/lib/ceilometer b/lib/ceilometer
index d9064e2..5d5b987 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -75,11 +75,14 @@
 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)
+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_COORDINATION_URL=${CEILOMETER_COORDINATION_URL:-}
+CEILOMETER_PIPELINE_INTERVAL=${CEILOMETER_PIPELINE_INTERVAL:-}
+
 # Tell Tempest this project is present
 TEMPEST_SERVICES+=,ceilometer
 
@@ -264,7 +267,7 @@
 
     if is_service_enabled mysql postgresql; then
         if [ "$CEILOMETER_BACKEND" = 'mysql' ] || [ "$CEILOMETER_BACKEND" = 'postgresql' ] ; then
-            recreate_database ceilometer utf8
+            recreate_database ceilometer
             $CEILOMETER_BIN_DIR/ceilometer-dbsync
         fi
     fi
diff --git a/lib/ceph b/lib/ceph
index 3b62a91..77b5726 100644
--- a/lib/ceph
+++ b/lib/ceph
@@ -70,6 +70,11 @@
 CEPH_REPLICAS=${CEPH_REPLICAS:-1}
 CEPH_REPLICAS_SEQ=$(seq ${CEPH_REPLICAS})
 
+# Connect to an existing Ceph cluster
+REMOTE_CEPH=$(trueorfalse False $REMOTE_CEPH)
+REMOTE_CEPH_ADMIN_KEY_PATH=${REMOTE_CEPH_ADMIN_KEY_PATH:-$CEPH_CONF_DIR/ceph.client.admin.keyring}
+
+
 # Functions
 # ------------
 
@@ -94,29 +99,69 @@
     sudo rm -f secret.xml
 }
 
+# undefine_virsh_secret() - Undefine Cinder key secret from libvirt
+function undefine_virsh_secret {
+    if is_service_enabled cinder || is_service_enabled nova; then
+        local virsh_uuid=$(sudo virsh secret-list | awk '/^ ?[0-9a-z]/ { print $1 }')
+        sudo virsh secret-undefine ${virsh_uuid} >/dev/null 2>&1
+    fi
+}
+
+
+# check_os_support_ceph() - Check if the operating system provides a decent version of Ceph
+function check_os_support_ceph {
+    if [[ ! ${DISTRO} =~ (trusty|f20|f21) ]]; then
+        echo "WARNING: your distro $DISTRO does not provide (at least) the Firefly release. Please use Ubuntu Trusty or Fedora 20 (and higher)"
+        if [[ "$FORCE_CEPH_INSTALL" != "yes" ]]; then
+            die $LINENO "If you wish to install Ceph on this distribution anyway run with FORCE_CEPH_INSTALL=yes"
+        fi
+        NO_UPDATE_REPOS=False
+    fi
+}
+
 # cleanup_ceph() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
-function cleanup_ceph {
+function cleanup_ceph_remote {
+    # do a proper cleanup from here to avoid leftover on the remote Ceph cluster
+    if is_service_enabled glance; then
+        sudo ceph osd pool delete $GLANCE_CEPH_POOL $GLANCE_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
+        sudo ceph auth del client.$GLANCE_CEPH_USER > /dev/null 2>&1
+    fi
+    if is_service_enabled cinder; then
+        sudo ceph osd pool delete $CINDER_CEPH_POOL $CINDER_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
+        sudo ceph auth del client.$CINDER_CEPH_USER > /dev/null 2>&1
+    fi
+    if is_service_enabled c-bak; then
+        sudo ceph osd pool delete $CINDER_BAK_CEPH_POOL $CINDER_BAK_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
+        sudo ceph auth del client.$CINDER_BAK_CEPH_USER > /dev/null 2>&1
+    fi
+    if is_service_enabled nova; then
+        iniset $NOVA_CONF libvirt rbd_secret_uuid ""
+        sudo ceph osd pool delete $NOVA_CEPH_POOL $NOVA_CEPH_POOL --yes-i-really-really-mean-it > /dev/null 2>&1
+    fi
+}
+
+function cleanup_ceph_embedded {
     sudo pkill -f ceph-mon
     sudo pkill -f ceph-osd
     sudo rm -rf ${CEPH_DATA_DIR}/*/*
-    sudo rm -rf ${CEPH_CONF_DIR}/*
     if egrep -q ${CEPH_DATA_DIR} /proc/mounts; then
         sudo umount ${CEPH_DATA_DIR}
     fi
     if [[ -e ${CEPH_DISK_IMAGE} ]]; then
         sudo rm -f ${CEPH_DISK_IMAGE}
     fi
-    uninstall_package ceph ceph-common python-ceph libcephfs1 > /dev/null 2>&1
-    if is_service_enabled cinder || is_service_enabled nova; then
-        local virsh_uuid=$(sudo virsh secret-list | awk '/^ ?[0-9a-z]/ { print $1 }')
-        sudo virsh secret-undefine ${virsh_uuid} >/dev/null 2>&1
-    fi
-    if is_service_enabled nova; then
-        iniset $NOVA_CONF libvirt rbd_secret_uuid ""
-    fi
 }
 
+function cleanup_ceph_general {
+    undefine_virsh_secret
+    uninstall_package ceph ceph-common python-ceph libcephfs1 > /dev/null 2>&1
+
+    # purge ceph config file and keys
+    sudo rm -rf ${CEPH_CONF_DIR}/*
+}
+
+
 # configure_ceph() - Set config files, create data dirs, etc
 function configure_ceph {
     local count=0
@@ -132,7 +177,7 @@
     sudo mkdir /var/lib/ceph/mon/ceph-$(hostname)
 
     # create a default ceph configuration file
-    sudo tee -a ${CEPH_CONF_FILE} > /dev/null <<EOF
+    sudo tee ${CEPH_CONF_FILE} > /dev/null <<EOF
 [global]
 fsid = ${CEPH_FSID}
 mon_initial_members = $(hostname)
@@ -205,14 +250,17 @@
     done
 }
 
-# configure_ceph_glance() - Glance config needs to come after Glance is set up
-function configure_ceph_glance {
+function configure_ceph_embedded_glance {
     # configure Glance service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${GLANCE_CEPH_POOL} ${GLANCE_CEPH_POOL_PG} ${GLANCE_CEPH_POOL_PGP}
     sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${GLANCE_CEPH_POOL} size ${CEPH_REPLICAS}
     if [[ $CEPH_REPLICAS -ne 1 ]]; then
         sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${GLANCE_CEPH_POOL} crush_ruleset ${RULE_ID}
     fi
+}
+
+# configure_ceph_glance() - Glance config needs to come after Glance is set up
+function configure_ceph_glance {
+    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${GLANCE_CEPH_POOL} ${GLANCE_CEPH_POOL_PG} ${GLANCE_CEPH_POOL_PGP}
     sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${GLANCE_CEPH_USER} mon "allow r" osd "allow class-read object_prefix rbd_children, allow rwx pool=${GLANCE_CEPH_POOL}" | sudo tee ${CEPH_CONF_DIR}/ceph.client.${GLANCE_CEPH_USER}.keyring
     sudo chown ${STACK_USER}:$(id -g -n $whoami) ${CEPH_CONF_DIR}/ceph.client.${GLANCE_CEPH_USER}.keyring
 
@@ -227,14 +275,17 @@
     iniset $GLANCE_API_CONF glance_store rbd_store_pool $GLANCE_CEPH_POOL
 }
 
-# configure_ceph_nova() - Nova config needs to come after Nova is set up
-function configure_ceph_nova {
+function configure_ceph_embedded_nova {
     # configure Nova service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${NOVA_CEPH_POOL} ${NOVA_CEPH_POOL_PG} ${NOVA_CEPH_POOL_PGP}
     sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${NOVA_CEPH_POOL} size ${CEPH_REPLICAS}
     if [[ $CEPH_REPLICAS -ne 1 ]]; then
         sudo -c ${CEPH_CONF_FILE} ceph osd pool set ${NOVA_CEPH_POOL} crush_ruleset ${RULE_ID}
     fi
+}
+
+# configure_ceph_nova() - Nova config needs to come after Nova is set up
+function configure_ceph_nova {
+    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${NOVA_CEPH_POOL} ${NOVA_CEPH_POOL_PG} ${NOVA_CEPH_POOL_PGP}
     iniset $NOVA_CONF libvirt rbd_user ${CINDER_CEPH_USER}
     iniset $NOVA_CONF libvirt rbd_secret_uuid ${CINDER_CEPH_UUID}
     iniset $NOVA_CONF libvirt inject_key false
@@ -250,15 +301,17 @@
     fi
 }
 
-# configure_ceph_cinder() - Cinder config needs to come after Cinder is set up
-function configure_ceph_cinder {
+function configure_ceph_embedded_cinder {
     # Configure Cinder service options, ceph pool, ceph user and ceph key
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${CINDER_CEPH_POOL} ${CINDER_CEPH_POOL_PG} ${CINDER_CEPH_POOL_PGP}
     sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_CEPH_POOL} size ${CEPH_REPLICAS}
     if [[ $CEPH_REPLICAS -ne 1 ]]; then
         sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_CEPH_POOL} crush_ruleset ${RULE_ID}
-
     fi
+}
+
+# configure_ceph_cinder() - Cinder config needs to come after Cinder is set up
+function configure_ceph_cinder {
+    sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${CINDER_CEPH_POOL} ${CINDER_CEPH_POOL_PG} ${CINDER_CEPH_POOL_PGP}
     sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_CEPH_USER} mon "allow r" osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_CEPH_POOL}, allow rwx pool=${NOVA_CEPH_POOL},allow rx pool=${GLANCE_CEPH_POOL}" | sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring
     sudo chown ${STACK_USER}:$(id -g -n $whoami) ${CEPH_CONF_DIR}/ceph.client.${CINDER_CEPH_USER}.keyring
 }
@@ -272,15 +325,12 @@
 }
 
 # install_ceph() - Collect source and prepare
+function install_ceph_remote {
+    install_package ceph-common
+}
+
 function install_ceph {
-    # NOTE(dtroyer): At some point it'll be easier to test for unsupported distros,
-    #                leveraging the list in stack.sh
-    if [[ ${os_CODENAME} =~ trusty ]] || [[ ${os_CODENAME} =~ Schrödinger’sCat ]] || [[ ${os_CODENAME} =~ Heisenbug ]]; then
-        NO_UPDATE_REPOS=False
-        install_package ceph
-    else
-        exit_distro_not_supported "Ceph since your distro doesn't provide (at least) the Firefly release. Please use Ubuntu Trusty or Fedora 19/20"
-    fi
+    install_package ceph
 }
 
 # start_ceph() - Start running processes, including screen
diff --git a/lib/cinder b/lib/cinder
index c106424..1bc6ddd 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -68,7 +68,7 @@
 # Maintain this here for backward-compatibility with the old configuration
 # DEPRECATED: Use CINDER_ENABLED_BACKENDS instead
 # Support for multi lvm backend configuration (default is no support)
-CINDER_MULTI_LVM_BACKEND=$(trueorfalse False $CINDER_MULTI_LVM_BACKEND)
+CINDER_MULTI_LVM_BACKEND=$(trueorfalse False CINDER_MULTI_LVM_BACKEND)
 
 # Default backends
 # The backend format is type:name where type is one of the supported backend
@@ -76,16 +76,16 @@
 # configuration and for the volume type name.  Multiple backends are
 # comma-separated.
 if [[ $CINDER_MULTI_LVM_BACKEND == "False" ]]; then
-    CINDER_ENABLED_BACKENDS=${CINDER_ENABLED_BACKENDS:-lvm:lvmdriver-1}
+    CINDER_ENABLED_BACKENDS=${CINDER_ENABLED_BACKENDS:-lvm:${DEFAULT_VOLUME_GROUP_NAME##*-}}
 else
-    CINDER_ENABLED_BACKENDS=${CINDER_ENABLED_BACKENDS:-lvm:lvmdriver-1,lvm:lvmdriver-2}
+    CINDER_ENABLED_BACKENDS=${CINDER_ENABLED_BACKENDS:-lvm:${DEFAULT_VOLUME_GROUP_NAME##*-},lvm:cinder}
 fi
 
 
 # Should cinder perform secure deletion of volumes?
 # Defaults to true, can be set to False to avoid this bug when testing:
 # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1023755
-CINDER_SECURE_DELETE=`trueorfalse True $CINDER_SECURE_DELETE`
+CINDER_SECURE_DELETE=$(trueorfalse True CINDER_SECURE_DELETE)
 
 # Cinder reports allocations back to the scheduler on periodic intervals
 # it turns out we can get an "out of space" issue when we run tests too
@@ -110,6 +110,12 @@
     done
 fi
 
+# Change the default nova_catalog_info and nova_catalog_admin_info values in
+# cinder so that the service name cinder is searching for matches that set for
+# nova in keystone.
+CINDER_NOVA_CATALOG_INFO=${CINDER_NOVA_CATALOG_INFO:-compute:nova:publicURL}
+CINDER_NOVA_CATALOG_ADMIN_INFO=${CINDER_NOVA_CATALOG_ADMIN_INFO:-compute:nova:adminURL}
+
 
 # Functions
 # ---------
@@ -205,6 +211,8 @@
 
     cp -p $CINDER_DIR/etc/cinder/policy.json $CINDER_CONF_DIR
 
+    rm -f $CINDER_CONF
+
     configure_cinder_rootwrap
 
     cp $CINDER_DIR/etc/cinder/api-paste.ini $CINDER_API_PASTE_INI
@@ -220,6 +228,9 @@
 
     configure_auth_token_middleware $CINDER_CONF cinder $CINDER_AUTH_CACHE_DIR
 
+    iniset $CINDER_CONF DEFAULT nova_catalog_info $CINDER_NOVA_CATALOG_INFO
+    iniset $CINDER_CONF DEFAULT nova_catalog_admin_info $CINDER_NOVA_CATALOG_ADMIN_INFO
+
     iniset $CINDER_CONF DEFAULT auth_strategy keystone
     iniset $CINDER_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
     iniset $CINDER_CONF DEFAULT verbose True
@@ -292,18 +303,6 @@
         configure_cinder_driver
     fi
 
-    if is_fedora && [[ $DISTRO =~ (rhel6) ]]; then
-        # Cinder clones are slightly larger due to some extra
-        # metadata.  RHEL6 will not allow auto-extending of LV's
-        # without this, leading to clones giving hard-to-track disk
-        # I/O errors.
-        # see https://bugzilla.redhat.com/show_bug.cgi?id=975052
-        sudo sed -i~ \
-            -e 's/snapshot_autoextend_threshold =.*/snapshot_autoextend_threshold = 80/' \
-            -e 's/snapshot_autoextend_percent =.*/snapshot_autoextend_percent = 20/' \
-            /etc/lvm/lvm.conf
-    fi
-
     iniset $CINDER_CONF DEFAULT osapi_volume_workers "$API_WORKERS"
 
     iniset $CINDER_CONF DEFAULT glance_api_servers "${GLANCE_SERVICE_PROTOCOL}://${GLANCE_HOSTPORT}"
@@ -376,7 +375,7 @@
 
     if is_service_enabled $DATABASE_BACKENDS; then
         # (Re)create cinder database
-        recreate_database cinder utf8
+        recreate_database cinder
 
         # Migrate cinder database
         $CINDER_BIN_DIR/cinder-manage db sync
@@ -384,15 +383,32 @@
 
     if is_service_enabled c-vol && [[ -n "$CINDER_ENABLED_BACKENDS" ]]; then
         local be be_name be_type
+        local has_lvm=0
         for be in ${CINDER_ENABLED_BACKENDS//,/ }; do
             be_type=${be%%:*}
             be_name=${be##*:}
+
+            if [[ $be_type == 'lvm' ]]; then
+                has_lvm=1
+            fi
+
             if type init_cinder_backend_${be_type} >/dev/null 2>&1; then
                 init_cinder_backend_${be_type} ${be_name}
             fi
         done
     fi
 
+    # Keep it simple, set a marker if there's an LVM backend
+    # use the created VG's to setup lvm filters
+    if [[ $has_lvm == 1 ]]; then
+        # Order matters here, not only obviously to make
+        # sure the VG's are created, but also some distros
+        # do some customizations to lvm.conf on init, we
+        # want to make sure we copy those over
+        sudo cp /etc/lvm/lvm.conf /etc/cinder/lvm.conf
+        configure_cinder_backend_conf_lvm
+    fi
+
     mkdir -p $CINDER_STATE_PATH/volumes
     create_cinder_cache_dir
 }
@@ -435,12 +451,8 @@
         if is_ubuntu; then
             sudo service tgt restart
         elif is_fedora; then
-            if [[ $DISTRO =~ (rhel6) ]]; then
-                sudo /sbin/service tgtd restart
-            else
-                # bypass redirection to systemctl during restart
-                sudo /sbin/service --skip-redirect tgtd restart
-            fi
+            # bypass redirection to systemctl during restart
+            sudo /sbin/service --skip-redirect tgtd restart
         elif is_suse; then
             restart_service tgtd
         else
diff --git a/lib/cinder_backends/ceph b/lib/cinder_backends/ceph
index 415ce94..7e9d2d3 100644
--- a/lib/cinder_backends/ceph
+++ b/lib/cinder_backends/ceph
@@ -54,11 +54,13 @@
     iniset $CINDER_CONF DEFAULT glance_api_version 2
 
     if is_service_enabled c-bak; then
-        # Configure Cinder backup service options, ceph pool, ceph user and ceph key
         sudo ceph -c ${CEPH_CONF_FILE} osd pool create ${CINDER_BAK_CEPH_POOL} ${CINDER_BAK_CEPH_POOL_PG} ${CINDER_BAK_CEPH_POOL_PGP}
-        sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_BAK_CEPH_POOL} size ${CEPH_REPLICAS}
-        if [[ $CEPH_REPLICAS -ne 1 ]]; then
-            sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_BAK_CEPH_POOL} crush_ruleset ${RULE_ID}
+        if [ "$REMOTE_CEPH" = "False" ]; then
+            # Configure Cinder backup service options, ceph pool, ceph user and ceph key
+            sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_BAK_CEPH_POOL} size ${CEPH_REPLICAS}
+            if [[ $CEPH_REPLICAS -ne 1 ]]; then
+                sudo ceph -c ${CEPH_CONF_FILE} osd pool set ${CINDER_BAK_CEPH_POOL} crush_ruleset ${RULE_ID}
+            fi
         fi
         sudo ceph -c ${CEPH_CONF_FILE} auth get-or-create client.${CINDER_BAK_CEPH_USER} mon "allow r" osd "allow class-read object_prefix rbd_children, allow rwx pool=${CINDER_BAK_CEPH_POOL}" | sudo tee ${CEPH_CONF_DIR}/ceph.client.${CINDER_BAK_CEPH_USER}.keyring
         sudo chown $(whoami):$(whoami) ${CEPH_CONF_DIR}/ceph.client.${CINDER_BAK_CEPH_USER}.keyring
diff --git a/lib/cinder_backends/lvm b/lib/cinder_backends/lvm
index a3ab5bf..4b9d8dc 100644
--- a/lib/cinder_backends/lvm
+++ b/lib/cinder_backends/lvm
@@ -14,10 +14,12 @@
 
 # CINDER_CONF
 # DATA_DIR
+# VOLUME_GROUP_NAME
 
 # clean_cinder_backend_lvm - called from clean_cinder()
 # configure_cinder_backend_lvm - called from configure_cinder()
 # init_cinder_backend_lvm - called from init_cinder()
+# configure_cinder_backend_conf_lvm - called from configure_cinder()
 
 
 # Save trace setting
@@ -25,156 +27,74 @@
 set +o xtrace
 
 
-# Defaults
-# --------
-
-# Name of the lvm volume groups to use/create for iscsi volumes
-# This monkey-motion is for compatibility with icehouse-generation Grenade
-# If ``VOLUME_GROUP`` is set, use it, otherwise we'll build a VG name based
-# on ``VOLUME_GROUP_NAME`` that includes the backend name
-# Grenade doesn't use ``VOLUME_GROUP2`` so it is left out
-VOLUME_GROUP_NAME=${VOLUME_GROUP:-${VOLUME_GROUP_NAME:-stack-volumes}}
-
 # TODO: resurrect backing device...need to know how to set values
 #VOLUME_BACKING_DEVICE=${VOLUME_BACKING_DEVICE:-}
 
-VOLUME_NAME_PREFIX=${VOLUME_NAME_PREFIX:-volume-}
-
-
 # Entry Points
 # ------------
 
-# Compatibility for getting a volume group name from either ``VOLUME_GROUP``
-# or from ``VOLUME_GROUP_NAME`` plus the backend name
-function get_volume_group_name {
-    local be_name=$1
-
-    # Again with the icehouse-generation compatibility
-    local volume_group_name=$VOLUME_GROUP_NAME
-    if [[ -z $VOLUME_GROUP ]]; then
-        volume_group_name+="-$be_name"
-    fi
-    echo $volume_group_name
-}
-
+# cleanup_cinder_backend_lvm - Delete volume group and remove backing file
+# cleanup_cinder_backend_lvm $be_name
 function cleanup_cinder_backend_lvm {
     local be_name=$1
 
-    # Again with the icehouse-generation compatibility
-    local volume_group_name=$(get_volume_group_name $be_name)
-
     # Campsite rule: leave behind a volume group at least as clean as we found it
-    _clean_lvm_lv ${volume_group_name} $VOLUME_NAME_PREFIX
-    _clean_lvm_backing_file ${volume_group_name} $DATA_DIR/${volume_group_name}-backing-file
+    clean_lvm_volume_group $VOLUME_GROUP_NAME-$be_name
 }
 
 # configure_cinder_backend_lvm - Set config files, create data dirs, etc
-# configure_cinder_backend_lvm $name
+# configure_cinder_backend_lvm $be_name
 function configure_cinder_backend_lvm {
     local be_name=$1
 
-    # Again with the icehouse-generation compatibility
-    local volume_group_name=$(get_volume_group_name $be_name)
-
     iniset $CINDER_CONF $be_name volume_backend_name $be_name
-    iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.lvm.LVMISCSIDriver"
-    iniset $CINDER_CONF $be_name volume_group $volume_group_name
+    iniset $CINDER_CONF $be_name volume_driver "cinder.volume.drivers.lvm.LVMVolumeDriver"
+    iniset $CINDER_CONF $be_name volume_group $VOLUME_GROUP_NAME-$be_name
+    iniset $CINDER_CONF $be_name iscsi_helper "tgtadm"
 
     if [[ "$CINDER_SECURE_DELETE" == "False" ]]; then
         iniset $CINDER_CONF $be_name volume_clear none
     fi
 }
 
-
+# init_cinder_backend_lvm - Initialize volume group
+# init_cinder_backend_lvm $be_name
 function init_cinder_backend_lvm {
     local be_name=$1
 
-    # Again with the icehouse-generation compatibility
-    local volume_group_name=$(get_volume_group_name $be_name)
-
     # Start with a clean volume group
-    _create_cinder_volume_group ${volume_group_name} $DATA_DIR/${volume_group_name}-backing-file
-
-    if is_fedora || is_suse; then
-        # service is not started by default
-        start_service tgtd
-    fi
-
-    # Remove iscsi targets
-    sudo tgtadm --op show --mode target | grep $VOLUME_NAME_PREFIX | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
-    _clean_lvm_lv ${volume_group_name} $VOLUME_NAME_PREFIX
+    init_lvm_volume_group $VOLUME_GROUP_NAME-$be_name $VOLUME_BACKING_FILE_SIZE
 }
 
+# configure_cinder_backend_conf_lvm - Sets device filter in /etc/cinder/lvm.conf
+# init_cinder_backend_lvm
+function configure_cinder_backend_conf_lvm {
+    local filter_suffix='"r/.*/" ]'
+    local filter_string="filter = [ "
+    local conf_entries=$(grep volume_group /etc/cinder/cinder.conf | sed "s/ //g")
+    local pv
+    local vg
+    local line
 
-# _clean_lvm_lv removes all cinder LVM volumes
-#
-# Usage: _clean_lvm_lv volume-group-name $VOLUME_NAME_PREFIX
-function _clean_lvm_lv {
-    local vg=$1
-    local lv_prefix=$2
-
-    # Clean out existing volumes
-    local lv
-    for lv in $(sudo lvs --noheadings -o lv_name $vg 2>/dev/null); do
-        # lv_prefix prefixes the LVs we want
-        if [[ "${lv#$lv_prefix}" != "$lv" ]]; then
-            sudo lvremove -f $vg/$lv
-        fi
-    done
-}
-
-# _clean_lvm_backing_file() removes the backing file of the
-# volume group used by cinder
-#
-# Usage: _clean_lvm_backing_file() volume-group-name backing-file-name
-function _clean_lvm_backing_file {
-    local vg=$1
-    local backing_file=$2
-
-    # if there is no logical volume left, it's safe to attempt a cleanup
-    # of the backing file
-    if [[ -z "$(sudo lvs --noheadings -o lv_name $vg 2>/dev/null)" ]]; then
-        # if the backing physical device is a loop device, it was probably setup by devstack
-        local vg_dev=$(sudo losetup -j $backing_file | awk -F':' '/backing-file/ { print $1}')
-        if [[ -n "$vg_dev" ]] && [[ -e "$vg_dev" ]]; then
-            sudo losetup -d $vg_dev
-            rm -f $backing_file
-        fi
-    fi
-}
-
-# _create_cinder_volume_group volume-group-name backing-file-name
-function _create_cinder_volume_group {
-    # According to the ``CINDER_MULTI_LVM_BACKEND`` value, configure one or two default volumes
-    # group called ``stack-volumes`` (and ``stack-volumes2``) for the volume
-    # service if it (they) does (do) not yet exist. If you don't wish to use a
-    # file backed volume group, create your own volume group called ``stack-volumes``
-    # and ``stack-volumes2`` before invoking ``stack.sh``.
-    #
-    # The two backing files are ``VOLUME_BACKING_FILE_SIZE`` in size, and they are stored in
-    # the ``DATA_DIR``.
-
-    local vg_name=$1
-    local backing_file=$2
-
-    if ! sudo vgs $vg_name; then
-        # TODO: fix device handling
-        if [ -z "$VOLUME_BACKING_DEVICE" ]; then
-            # Only create if the file doesn't already exists
-            [[ -f $backing_file ]] || truncate -s $VOLUME_BACKING_FILE_SIZE $backing_file
-            local vg_dev=`sudo losetup -f --show $backing_file`
-
-            # Only create if the loopback device doesn't contain $VOLUME_GROUP
-            if ! sudo vgs $vg_name; then
-                sudo vgcreate $vg_name $vg_dev
+    for pv_info in $(sudo pvs --noheadings -o name,vg_name --separator ';'); do
+        IFS=';' read pv vg <<< $pv_info
+        for line in ${conf_entries}; do
+            IFS='=' read label group <<< $line
+            group=$(echo $group|sed "s/^ *//g")
+            if [[ "$vg" == "$group" ]]; then
+                new="\"a$pv/\", "
+                filter_string=$filter_string$new
             fi
-        else
-            sudo vgcreate $vg_name $VOLUME_BACKING_DEVICE
-        fi
-    fi
+        done
+    done
+    filter_string=$filter_string$filter_suffix
+
+    # FIXME(jdg): Possible odd case that the lvm.conf file has been modified
+    # and doesn't have a filter entry to search/replace.  For devstack don't
+    # know that we care, but could consider adding a check and add
+    sudo sed -i "s#^[ \t]*filter.*#    $filter_string#g" /etc/cinder/lvm.conf
+    echo "set LVM filter_strings: $filter_string"
 }
-
-
 # Restore xtrace
 $MY_XTRACE
 
diff --git a/lib/database b/lib/database
index 366d2b3..b114e9e 100644
--- a/lib/database
+++ b/lib/database
@@ -23,6 +23,7 @@
 XTRACE=$(set +o | grep xtrace)
 set +o xtrace
 
+DATABASE_BACKENDS=""
 
 # Register a database backend
 #
@@ -30,7 +31,7 @@
 #
 # This is required to be defined before the specific database scripts are sourced
 function register_database {
-    [ -z "$DATABASE_BACKENDS" ] && DATABASE_BACKENDS=$1 || DATABASE_BACKENDS+=" $1"
+    DATABASE_BACKENDS+=" $1"
 }
 
 # Sourcing the database libs sets DATABASE_BACKENDS with the available list
@@ -98,11 +99,9 @@
 
 # Recreate a given database
 #  $1 The name of the database
-#  $2 The character set/encoding of the database
 function recreate_database {
     local db=$1
-    local charset=$2
-    recreate_database_$DATABASE_TYPE $db $charset
+    recreate_database_$DATABASE_TYPE $db
 }
 
 # Install the database
diff --git a/lib/databases/mysql b/lib/databases/mysql
index d39d966..72c0f82 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -14,38 +14,42 @@
 
 register_database mysql
 
+# Linux distros, thank you for being incredibly consistent
+MYSQL=mysql
+if is_fedora; then
+    MYSQL=mariadb
+fi
 
 # Functions
 # ---------
 
 # Get rid of everything enough to cleanly change database backends
 function cleanup_database_mysql {
+    stop_service $MYSQL
     if is_ubuntu; then
         # Get ruthless with mysql
         stop_service $MYSQL
-        apt_get purge -y mysql*
+        apt_get purge -y mysql* mariadb*
         sudo rm -rf /var/lib/mysql
         sudo rm -rf /etc/mysql
         return
     elif is_fedora; then
-        if [[ $DISTRO =~ (rhel6) ]]; then
-            MYSQL=mysqld
-        else
-            MYSQL=mariadb
-        fi
+        stop_service mariadb
+        uninstall_package mariadb-server
+        sudo rm -rf /var/lib/mysql
     elif is_suse; then
-        MYSQL=mysql
+        stop_service mysql
+        uninstall_package mysql-community-server
+        sudo rm -rf /var/lib/mysql
     else
         return
     fi
-    stop_service $MYSQL
 }
 
 function recreate_database_mysql {
     local db=$1
-    local charset=$2
     mysql -u$DATABASE_USER -p$DATABASE_PASSWORD -h$MYSQL_HOST -e "DROP DATABASE IF EXISTS $db;"
-    mysql -u$DATABASE_USER -p$DATABASE_PASSWORD -h$MYSQL_HOST -e "CREATE DATABASE $db CHARACTER SET $charset;"
+    mysql -u$DATABASE_USER -p$DATABASE_PASSWORD -h$MYSQL_HOST -e "CREATE DATABASE $db CHARACTER SET utf8;"
 }
 
 function configure_database_mysql {
@@ -56,11 +60,7 @@
         my_conf=/etc/mysql/my.cnf
         mysql=mysql
     elif is_fedora; then
-        if [[ $DISTRO =~ (rhel6) ]]; then
-            mysql=mysqld
-        else
-            mysql=mariadb
-        fi
+        mysql=mariadb
         my_conf=/etc/my.cnf
     elif is_suse; then
         my_conf=/etc/my.cnf
@@ -96,7 +96,7 @@
 
     if [[ "$DATABASE_QUERY_LOGGING" == "True" ]]; then
         echo_summary "Enabling MySQL query logging"
-        if is_fedora && ! [[ $DISTRO =~ (rhel6) ]]; then
+        if is_fedora; then
             slow_log=/var/log/mariadb/mariadb-slow.log
         else
             slow_log=/var/log/mysql/mysql-slow.log
@@ -123,10 +123,10 @@
     if is_ubuntu; then
         # Seed configuration with mysql password so that apt-get install doesn't
         # prompt us for a password upon install.
-        cat <<MYSQL_PRESEED | sudo debconf-set-selections
-mysql-server-5.1 mysql-server/root_password password $DATABASE_PASSWORD
-mysql-server-5.1 mysql-server/root_password_again password $DATABASE_PASSWORD
-mysql-server-5.1 mysql-server/start_on_boot boolean true
+        sudo debconf-set-selections <<MYSQL_PRESEED
+mysql-server mysql-server/root_password password $DATABASE_PASSWORD
+mysql-server mysql-server/root_password_again password $DATABASE_PASSWORD
+mysql-server mysql-server/start_on_boot boolean true
 MYSQL_PRESEED
     fi
 
@@ -144,11 +144,7 @@
     fi
     # Install mysql-server
     if is_fedora; then
-        if [[ $DISTRO =~ (rhel6) ]]; then
-            install_package mysql-server
-        else
-            install_package mariadb-server
-        fi
+        install_package mariadb-server
     elif is_ubuntu; then
         install_package mysql-server
     elif is_suse; then
diff --git a/lib/databases/postgresql b/lib/databases/postgresql
index 76491c4..317e0eb 100644
--- a/lib/databases/postgresql
+++ b/lib/databases/postgresql
@@ -37,10 +37,9 @@
 
 function recreate_database_postgresql {
     local db=$1
-    local charset=$2
     # Avoid unsightly error when calling dropdb when the database doesn't exist
     psql -h$DATABASE_HOST -U$DATABASE_USER -dtemplate1 -c "DROP DATABASE IF EXISTS $db"
-    createdb -h $DATABASE_HOST -U$DATABASE_USER -l C -T template0 -E $charset $db
+    createdb -h $DATABASE_HOST -U$DATABASE_USER -l C -T template0 -E utf8 $db
 }
 
 function configure_database_postgresql {
@@ -50,11 +49,7 @@
         pg_hba=/var/lib/pgsql/data/pg_hba.conf
         pg_conf=/var/lib/pgsql/data/postgresql.conf
         if ! sudo [ -e $pg_hba ]; then
-            if ! [[ $DISTRO =~ (rhel6) ]]; then
-                sudo postgresql-setup initdb
-            else
-                sudo service postgresql initdb
-            fi
+            sudo postgresql-setup initdb
         fi
     elif is_ubuntu; then
         pg_dir=`find /etc/postgresql -name pg_hba.conf|xargs dirname`
diff --git a/lib/dib b/lib/dib
index 177f4c1..809217b 100644
--- a/lib/dib
+++ b/lib/dib
@@ -26,7 +26,7 @@
 # NOTE: Setting DIB_APT_SOURCES assumes you will be building
 # Debian/Ubuntu based images. Leave unset for other flavors.
 DIB_APT_SOURCES=${DIB_APT_SOURCES:-""}
-DIB_BUILD_OFFLINE=$(trueorfalse False $DIB_BUILD_OFFLINE)
+DIB_BUILD_OFFLINE=$(trueorfalse False DIB_BUILD_OFFLINE)
 DIB_IMAGE_CACHE=$DATA_DIR/diskimage-builder/image-create
 DIB_PIP_REPO=$DATA_DIR/diskimage-builder/pip-repo
 DIB_PIP_REPO_PORT=${DIB_PIP_REPO_PORT:-8899}
diff --git a/lib/dstat b/lib/dstat
index 8f456a8..d1db469 100644
--- a/lib/dstat
+++ b/lib/dstat
@@ -20,15 +20,19 @@
 # Defaults
 # --------
 # for DSTAT logging
-DSTAT_FILE=${DSTAT_FILE:-"dstat.txt"}
+DSTAT_FILE=${DSTAT_FILE:-"dstat.log"}
 
 
 # start_dstat() - Start running processes, including screen
 function start_dstat {
     # A better kind of sysstat, with the top process per time slice
-    DSTAT_OPTS="-tcmndrylpg --top-cpu-adv"
-    if [[ -n ${SCREEN_LOGDIR} ]]; then
-        screen_it dstat "cd $TOP_DIR; dstat $DSTAT_OPTS | tee $SCREEN_LOGDIR/$DSTAT_FILE"
+    DSTAT_OPTS="-tcmndrylpg --top-cpu-adv --top-io-adv"
+    if [[ -n ${LOGDIR} ]]; then
+        screen_it dstat "cd $TOP_DIR; dstat $DSTAT_OPTS | tee $LOGDIR/$DSTAT_FILE"
+        if [[ -n ${SCREEN_LOGDIR} ]]; then
+            # Drop the backward-compat symlink
+            ln -sf $LOGDIR/$DSTAT_FILE ${SCREEN_LOGDIR}/$DSTAT_FILE
+        fi
     else
         screen_it dstat "dstat $DSTAT_OPTS"
     fi
diff --git a/lib/glance b/lib/glance
index 8cda6be..8768761 100644
--- a/lib/glance
+++ b/lib/glance
@@ -279,7 +279,7 @@
     mkdir -p $GLANCE_CACHE_DIR
 
     # (Re)create glance database
-    recreate_database glance utf8
+    recreate_database glance
 
     # Migrate glance database
     $GLANCE_BIN_DIR/glance-manage db_sync
diff --git a/lib/heat b/lib/heat
index 4e72cae..82bbc9f 100644
--- a/lib/heat
+++ b/lib/heat
@@ -10,6 +10,7 @@
 # Dependencies:
 #
 # - functions
+# - dib (if HEAT_CREATE_TEST_IMAGE=True)
 
 # stack.sh
 # ---------
@@ -37,14 +38,20 @@
 HEAT_CFNTOOLS_DIR=$DEST/heat-cfntools
 HEAT_TEMPLATES_REPO_DIR=$DEST/heat-templates
 HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
-HEAT_STANDALONE=`trueorfalse False $HEAT_STANDALONE`
+HEAT_STANDALONE=$(trueorfalse False HEAT_STANDALONE)
+HEAT_ENABLE_ADOPT_ABANDON=$(trueorfalse False HEAT_ENABLE_ADOPT_ABANDON)
 HEAT_CONF_DIR=/etc/heat
 HEAT_CONF=$HEAT_CONF_DIR/heat.conf
 HEAT_ENV_DIR=$HEAT_CONF_DIR/environment.d
 HEAT_TEMPLATES_DIR=$HEAT_CONF_DIR/templates
-HEAT_STACK_DOMAIN=`trueorfalse True $HEAT_STACK_DOMAIN`
+HEAT_STACK_DOMAIN=$(trueorfalse True HEAT_STACK_DOMAIN)
 HEAT_API_HOST=${HEAT_API_HOST:-$HOST_IP}
 HEAT_API_PORT=${HEAT_API_PORT:-8004}
+HEAT_FUNCTIONAL_IMAGE_ELEMENTS=${HEAT_FUNCTIONAL_IMAGE_ELEMENTS:-\
+vm fedora selinux-permissive pypi  os-collect-config os-refresh-config \
+os-apply-config heat-cfntools heat-config heat-config-cfn-init \
+heat-config-puppet heat-config-script}
+
 
 # other default options
 HEAT_DEFERRED_AUTH=${HEAT_DEFERRED_AUTH:-trusts}
@@ -114,7 +121,18 @@
         setup_colorized_logging $HEAT_CONF DEFAULT tenant user
     fi
 
-    configure_auth_token_middleware $HEAT_CONF heat $HEAT_AUTH_CACHE_DIR
+    # NOTE(jamielennox): heat re-uses specific values from the
+    # keystone_authtoken middleware group and so currently fails when using the
+    # auth plugin setup. This should be fixed in heat.  Heat is also the only
+    # service that requires the auth_uri to include a /v2.0. Remove this custom
+    # setup when bug #1300246 is resolved.
+    iniset $HEAT_CONF keystone_authtoken identity_uri $KEYSTONE_AUTH_URI
+    iniset $HEAT_CONF keystone_authtoken auth_uri $KEYSTONE_SERVICE_URI/v2.0
+    iniset $HEAT_CONF keystone_authtoken admin_user heat
+    iniset $HEAT_CONF keystone_authtoken admin_password $SERVICE_PASSWORD
+    iniset $HEAT_CONF keystone_authtoken admin_tenant_name $SERVICE_TENANT_NAME
+    iniset $HEAT_CONF keystone_authtoken cafile $SSL_BUNDLE_FILE
+    iniset $HEAT_CONF keystone_authtoken signing_dir $HEAT_AUTH_CACHE_DIR
 
     if is_ssl_enabled_service "key"; then
         iniset $HEAT_CONF clients_keystone ca_file $SSL_BUNDLE_FILE
@@ -151,6 +169,11 @@
         iniset $HEAT_CONF clients_cinder ca_file $SSL_BUNDLE_FILE
     fi
 
+    if [[ "$HEAT_ENABLE_ADOPT_ABANDON" = "True" ]]; then
+        iniset $HEAT_CONF DEFAULT enable_stack_adopt true
+        iniset $HEAT_CONF DEFAULT enable_stack_abandon true
+    fi
+
     # heat environment
     sudo mkdir -p $HEAT_ENV_DIR
     sudo chown $STACK_USER $HEAT_ENV_DIR
@@ -169,7 +192,7 @@
 function init_heat {
 
     # (re)create heat database
-    recreate_database heat utf8
+    recreate_database heat
 
     $HEAT_DIR/bin/heat-manage db_sync
     create_heat_cache_dir
@@ -259,23 +282,21 @@
     if [[ "$HEAT_STACK_DOMAIN" == "True" ]]; then
         # Note we have to pass token/endpoint here because the current endpoint and
         # version negotiation in OSC means just --os-identity-api-version=3 won't work
-        local ks_endpoint_v3="$KEYSTONE_SERVICE_URI/v3"
-
-        D_ID=$(openstack --os-token $OS_TOKEN --os-url=$ks_endpoint_v3 \
+        D_ID=$(openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
             --os-identity-api-version=3 domain list | grep ' heat ' | get_field 1)
 
         if [[ -z "$D_ID" ]]; then
-            D_ID=$(openstack --os-token $OS_TOKEN --os-url=$ks_endpoint_v3 \
+            D_ID=$(openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
                 --os-identity-api-version=3 domain create heat \
                 --description "Owns users and projects created by heat" \
                 | grep ' id ' | get_field 2)
             iniset $HEAT_CONF DEFAULT stack_user_domain_id ${D_ID}
 
-            openstack --os-token $OS_TOKEN --os-url=$ks_endpoint_v3 \
+            openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
                 --os-identity-api-version=3 user create --password $SERVICE_PASSWORD \
                 --domain $D_ID heat_domain_admin \
                 --description "Manages users and projects created by heat"
-            openstack --os-token $OS_TOKEN --os-url=$ks_endpoint_v3 \
+            openstack --os-token $OS_TOKEN --os-url=$KEYSTONE_SERVICE_URI_V3 \
                 --os-identity-api-version=3 role add \
                 --user heat_domain_admin --domain ${D_ID} admin
             iniset $HEAT_CONF DEFAULT stack_domain_admin heat_domain_admin
@@ -286,19 +307,20 @@
 
 # build_heat_functional_test_image() - Build and upload functional test image
 function build_heat_functional_test_image {
-    build_dib_pip_repo "$OCC_DIR $OAC_DIR $ORC_DIR $HEAT_CFNTOOLS_DIR"
-    local image_name=heat-functional-tests-image
+    if is_service_enabled dib; then
+        build_dib_pip_repo "$OCC_DIR $OAC_DIR $ORC_DIR $HEAT_CFNTOOLS_DIR"
+        local image_name=heat-functional-tests-image
 
-    # The elements to invoke disk-image-create with
-    local image_elements="vm fedora selinux-permissive pypi \
-        os-collect-config os-refresh-config os-apply-config heat-cfntools \
-        heat-config heat-config-cfn-init heat-config-puppet heat-config-script"
+        # Elements path for tripleo-image-elements and heat-templates software-config
+        local elements_path=$TIE_DIR/elements:$HEAT_TEMPLATES_REPO_DIR/hot/software-config/elements
 
-    # Elements path for tripleo-image-elements and heat-templates software-config
-    local elements_path=$TIE_DIR/elements:$HEAT_TEMPLATES_REPO_DIR/hot/software-config/elements
-
-    disk_image_create_upload "$image_name" "$image_elements" "$elements_path"
-    iniset $TEMPEST_CONFIG orchestration image_ref $image_name
+        disk_image_create_upload "$image_name" "$HEAT_FUNCTIONAL_IMAGE_ELEMENTS" "$elements_path"
+        iniset $TEMPEST_CONFIG orchestration image_ref $image_name
+    else
+        echo "Error, HEAT_CREATE_TEST_IMAGE=True requires dib" >&2
+        echo "Add \"enable_service dib\" to your localrc" >&2
+        exit 1
+    fi
 }
 
 # Restore xtrace
diff --git a/lib/horizon b/lib/horizon
index fee2ef0..122d516 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -72,14 +72,6 @@
 # cleanup_horizon() - Remove residual data files, anything left over from previous
 # runs that a clean run would need to clean up
 function cleanup_horizon {
-    if is_fedora && [[ $DISTRO =~ (rhel6) ]]; then
-        # If ``/usr/bin/node`` points into ``$DEST``
-        # we installed it via ``install_nodejs``
-        if [[ $(readlink -f /usr/bin/node) =~ ($DEST) ]]; then
-            sudo rm /usr/bin/node
-        fi
-    fi
-
     local horizon_conf=$(apache_site_config_for horizon)
     sudo rm -f $horizon_conf
 }
@@ -173,7 +165,7 @@
     # Apache installation, because we mark it NOPRIME
     install_apache_wsgi
 
-    git_clone $HORIZON_REPO $HORIZON_DIR $HORIZON_BRANCH $HORIZON_TAG
+    git_clone $HORIZON_REPO $HORIZON_DIR $HORIZON_BRANCH
 }
 
 # start_horizon() - Start running processes, including screen
diff --git a/lib/ironic b/lib/ironic
index 55272b9..2075a9c 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -42,6 +42,9 @@
 IRONIC_ROOTWRAP_CONF=$IRONIC_CONF_DIR/rootwrap.conf
 IRONIC_POLICY_JSON=$IRONIC_CONF_DIR/policy.json
 
+# Deploy callback timeout can be changed from its default (1800), if required.
+IRONIC_CALLBACK_TIMEOUT=${IRONIC_CALLBACK_TIMEOUT:-}
+
 # Deploy to hardware platform
 IRONIC_HW_NODE_CPU=${IRONIC_HW_NODE_CPU:-1}
 IRONIC_HW_NODE_RAM=${IRONIC_HW_NODE_RAM:-512}
@@ -57,7 +60,7 @@
 # Set up defaults for functional / integration testing
 IRONIC_SCRIPTS_DIR=${IRONIC_SCRIPTS_DIR:-$TOP_DIR/tools/ironic/scripts}
 IRONIC_TEMPLATES_DIR=${IRONIC_TEMPLATES_DIR:-$TOP_DIR/tools/ironic/templates}
-IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False $IRONIC_BAREMETAL_BASIC_OPS)
+IRONIC_BAREMETAL_BASIC_OPS=$(trueorfalse False IRONIC_BAREMETAL_BASIC_OPS)
 IRONIC_ENABLED_DRIVERS=${IRONIC_ENABLED_DRIVERS:-fake,pxe_ssh,pxe_ipmitool}
 IRONIC_SSH_USERNAME=${IRONIC_SSH_USERNAME:-`whoami`}
 IRONIC_SSH_KEY_DIR=${IRONIC_SSH_KEY_DIR:-$IRONIC_DATA_DIR/ssh_keys}
@@ -84,7 +87,7 @@
 IRONIC_VM_LOG_DIR=${IRONIC_VM_LOG_DIR:-$IRONIC_DATA_DIR/logs/}
 
 # Use DIB to create deploy ramdisk and kernel.
-IRONIC_BUILD_DEPLOY_RAMDISK=`trueorfalse True $IRONIC_BUILD_DEPLOY_RAMDISK`
+IRONIC_BUILD_DEPLOY_RAMDISK=$(trueorfalse True IRONIC_BUILD_DEPLOY_RAMDISK)
 # If not use DIB, these files are used as deploy ramdisk/kernel.
 # (The value must be a absolute path)
 IRONIC_DEPLOY_RAMDISK=${IRONIC_DEPLOY_RAMDISK:-}
@@ -113,7 +116,7 @@
 TEMPEST_SERVICES+=,ironic
 
 # Enable iPXE
-IRONIC_IPXE_ENABLED=$(trueorfalse False $IRONIC_IPXE_ENABLED)
+IRONIC_IPXE_ENABLED=$(trueorfalse False IRONIC_IPXE_ENABLED)
 IRONIC_HTTP_DIR=${IRONIC_HTTP_DIR:-$IRONIC_DATA_DIR/httpboot}
 IRONIC_HTTP_SERVER=${IRONIC_HTTP_SERVER:-$HOST_IP}
 IRONIC_HTTP_PORT=${IRONIC_HTTP_PORT:-8088}
@@ -300,6 +303,9 @@
     iniset $IRONIC_CONF_FILE DEFAULT rootwrap_config $IRONIC_ROOTWRAP_CONF
     iniset $IRONIC_CONF_FILE DEFAULT enabled_drivers $IRONIC_ENABLED_DRIVERS
     iniset $IRONIC_CONF_FILE conductor api_url $IRONIC_SERVICE_PROTOCOL://$HOST_IP:$IRONIC_SERVICE_PORT
+    if [[ -n "$IRONIC_CALLBACK_TIMEOUT" ]]; then
+        iniset $IRONIC_CONF_FILE conductor deploy_callback_timeout $IRONIC_CALLBACK_TIMEOUT
+    fi
     iniset $IRONIC_CONF_FILE pxe tftp_server $IRONIC_TFTPSERVER_IP
     iniset $IRONIC_CONF_FILE pxe tftp_root $IRONIC_TFTPBOOT_DIR
     iniset $IRONIC_CONF_FILE pxe tftp_master_path $IRONIC_TFTPBOOT_DIR/master_images
@@ -380,7 +386,7 @@
 # init_ironic() - Initialize databases, etc.
 function init_ironic {
     # (Re)create  ironic database
-    recreate_database ironic utf8
+    recreate_database ironic
 
     # Migrate ironic database
     $IRONIC_BIN_DIR/ironic-dbsync --config-file=$IRONIC_CONF_FILE
@@ -455,7 +461,11 @@
     # intentional sleep to make sure the tag has been set to port
     sleep 10
 
-    local tapdev=$(sudo ip netns exec qdhcp-${ironic_net_id} ip link list | grep " tap" | cut -d':' -f2 | cut -b2-)
+    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-)
+    else
+        local tapdev=$(sudo ip link list | grep " tap" | cut -d':' -f2 | cut -b2-)
+    fi
     local tag_id=$(sudo ovs-vsctl show |grep ${tapdev} -A1 -m1 | grep tag | cut -d':' -f2 | cut -b2-)
 
     # make sure veth pair is not existing, otherwise delete its links
diff --git a/lib/keystone b/lib/keystone
index 1599fa5..afa7f00 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -71,6 +71,7 @@
 
 # Select Keystone's token format
 # Choose from 'UUID', 'PKI', or 'PKIZ'
+KEYSTONE_TOKEN_FORMAT=${KEYSTONE_TOKEN_FORMAT:-}
 KEYSTONE_TOKEN_FORMAT=$(echo ${KEYSTONE_TOKEN_FORMAT} | tr '[:upper:]' '[:lower:]')
 
 # Set Keystone interface configuration
@@ -106,6 +107,10 @@
 KEYSTONE_AUTH_URI=${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_AUTH_HOST}:${KEYSTONE_AUTH_PORT}
 KEYSTONE_SERVICE_URI=${KEYSTONE_SERVICE_PROTOCOL}://${KEYSTONE_SERVICE_HOST}:${KEYSTONE_SERVICE_PORT}
 
+# V3 URIs
+KEYSTONE_AUTH_URI_V3=$KEYSTONE_AUTH_URI/v3
+KEYSTONE_SERVICE_URI_V3=$KEYSTONE_SERVICE_URI/v3
+
 # Functions
 # ---------
 # cleanup_keystone() - Remove residual data files, anything left over from previous
@@ -394,6 +399,9 @@
     get_or_add_user_role $another_role $demo_user $demo_tenant
     get_or_add_user_role $member_role $demo_user $invis_tenant
 
+    get_or_create_group "developers" "default" "openstack developers"
+    get_or_create_group "testers" "default"
+
     # Keystone
     if [[ "$KEYSTONE_CATALOG_BACKEND" = 'sql' ]]; then
 
@@ -407,15 +415,6 @@
     fi
 }
 
-# Configure the API version for the OpenStack projects.
-# configure_API_version conf_file version [section]
-function configure_API_version {
-    local conf_file=$1
-    local api_version=$2
-    local section=${3:-keystone_authtoken}
-    iniset $conf_file $section auth_uri $KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:$KEYSTONE_SERVICE_PORT/v$api_version
-}
-
 # Configure the service to use the auth token middleware.
 #
 # configure_auth_token_middleware conf_file admin_user signing_dir [section]
@@ -429,15 +428,16 @@
     local signing_dir=$3
     local section=${4:-keystone_authtoken}
 
-    iniset $conf_file $section auth_host $KEYSTONE_AUTH_HOST
-    iniset $conf_file $section auth_port $KEYSTONE_AUTH_PORT
-    iniset $conf_file $section auth_protocol $KEYSTONE_AUTH_PROTOCOL
-    iniset $conf_file $section identity_uri $KEYSTONE_AUTH_URI
+    iniset $conf_file $section auth_plugin password
+    iniset $conf_file $section auth_url $KEYSTONE_AUTH_URI
+    iniset $conf_file $section username $admin_user
+    iniset $conf_file $section password $SERVICE_PASSWORD
+    iniset $conf_file $section user_domain_id default
+    iniset $conf_file $section project_name $SERVICE_TENANT_NAME
+    iniset $conf_file $section project_domain_id default
+
+    iniset $conf_file $section auth_uri $KEYSTONE_SERVICE_URI
     iniset $conf_file $section cafile $SSL_BUNDLE_FILE
-    configure_API_version $conf_file $IDENTITY_API_VERSION $section
-    iniset $conf_file $section admin_tenant_name $SERVICE_TENANT_NAME
-    iniset $conf_file $section admin_user $admin_user
-    iniset $conf_file $section admin_password $SERVICE_PASSWORD
     iniset $conf_file $section signing_dir $signing_dir
 }
 
@@ -448,7 +448,7 @@
     fi
 
     # (Re)create keystone database
-    recreate_database keystone utf8
+    recreate_database keystone
 
     # Initialize keystone database
     $KEYSTONE_DIR/bin/keystone-manage db_sync
diff --git a/lib/lvm b/lib/lvm
new file mode 100644
index 0000000..4ef260d
--- /dev/null
+++ b/lib/lvm
@@ -0,0 +1,124 @@
+# lib/lvm
+# Configure the default LVM volume group used by Cinder and Nova
+
+# Dependencies:
+#
+# - ``functions`` file
+# - ``cinder`` configurations
+
+# DATA_DIR
+
+# clean_default_volume_group - called from clean()
+# configure_default_volume_group - called from configure()
+# init_default_volume_group - called from init()
+
+
+# Save trace setting
+MY_XTRACE=$(set +o | grep xtrace)
+set +o xtrace
+
+
+# Defaults
+# --------
+# Name of the lvm volume groups to use/create for iscsi volumes
+# This monkey-motion is for compatibility with icehouse-generation Grenade
+# If ``VOLUME_GROUP`` is set, use it, otherwise we'll build a VG name based
+# on ``VOLUME_GROUP_NAME`` that includes the backend name
+# Grenade doesn't use ``VOLUME_GROUP2`` so it is left out
+VOLUME_GROUP_NAME=${VOLUME_GROUP:-${VOLUME_GROUP_NAME:-stack-volumes}}
+DEFAULT_VOLUME_GROUP_NAME=$VOLUME_GROUP_NAME-default
+
+# Backing file name is of the form $VOLUME_GROUP$BACKING_FILE_SUFFIX
+BACKING_FILE_SUFFIX=-backing-file
+
+
+# Entry Points
+# ------------
+
+# _clean_lvm_volume_group removes all default LVM volumes
+#
+# Usage: clean_lvm_volume_group $vg
+function _clean_lvm_volume_group {
+    local vg=$1
+
+    # Clean out existing volumes
+    sudo lvremove -f $vg
+}
+
+# _clean_lvm_backing_file() removes the backing file of the
+# volume group
+#
+# Usage: _clean_lvm_backing_file() $backing_file
+function _clean_lvm_backing_file {
+    local backing_file=$1
+
+    # if the backing physical device is a loop device, it was probably setup by devstack
+    if [[ -n "$backing_file" ]] && [[ -e "$backing_file" ]]; then
+        local vg_dev=$(sudo losetup -j $backing_file | awk -F':' '/'$BACKING_FILE_SUFFIX'/ { print $1}')
+        sudo losetup -d $vg_dev
+        rm -f $backing_file
+    fi
+}
+
+# clean_lvm_volume_group() cleans up the volume group and removes the
+# backing file
+#
+# Usage: clean_lvm_volume_group $vg
+function clean_lvm_volume_group {
+    local vg=$1
+
+    _clean_lvm_volume_group $vg
+    # if there is no logical volume left, it's safe to attempt a cleanup
+    # of the backing file
+    if [[ -z "$(sudo lvs --noheadings -o lv_name $vg 2>/dev/null)" ]]; then
+        _clean_lvm_backing_file $DATA_DIR/$vg$BACKING_FILE_SUFFIX
+    fi
+}
+
+
+# _create_volume_group creates default volume group
+#
+# Usage: _create_lvm_volume_group() $vg $size
+function _create_lvm_volume_group {
+    local vg=$1
+    local size=$2
+
+    local backing_file=$DATA_DIR/$vg$BACKING_FILE_SUFFIX
+    if ! sudo vgs $vg; then
+        # Only create if the file doesn't already exists
+        [[ -f $DATA_DIR/$backing_file ]] || truncate -s $size $backing_file
+        local vg_dev=`sudo losetup -f --show $backing_file`
+
+        # Only create volume group if it doesn't already exist
+        if ! sudo vgs $vg; then
+            sudo vgcreate $vg $vg_dev
+        fi
+    fi
+}
+
+# init_lvm_volume_group() initializes the volume group creating the backing
+# file if necessary
+#
+# Usage: init_lvm_volume_group() $vg
+function init_lvm_volume_group {
+    local vg=$1
+    local size=$2
+    # Start with a clean volume group
+    _create_lvm_volume_group $vg $size
+
+    if is_fedora || is_suse; then
+        # service is not started by default
+        start_service tgtd
+    fi
+
+    # Remove iscsi targets
+    sudo tgtadm --op show --mode target | grep Target | cut -f3 -d ' ' | sudo xargs -n1 tgt-admin --delete || true
+
+    _clean_lvm_volume_group $vg
+}
+
+# Restore xtrace
+$MY_XTRACE
+
+# mode: shell-script
+# End:
diff --git a/lib/neutron b/lib/neutron
index 8a8fe3c..0f49476 100755
--- a/lib/neutron
+++ b/lib/neutron
@@ -534,12 +534,24 @@
     TENANT_ID=$(openstack project list | grep " demo " | get_field 1)
     die_if_not_set $LINENO TENANT_ID "Failure retrieving TENANT_ID for demo"
 
+    # Allow drivers that need to create an initial network to do so here
+    if type -p neutron_plugin_create_initial_network_profile > /dev/null; then
+        neutron_plugin_create_initial_network_profile $PHYSICAL_NETWORK
+    fi
+
     if is_provider_network; then
         die_if_not_set $LINENO PHYSICAL_NETWORK "You must specify the PHYSICAL_NETWORK"
         die_if_not_set $LINENO PROVIDER_NETWORK_TYPE "You must specifiy the PROVIDER_NETWORK_TYPE"
         NET_ID=$(neutron net-create $PHYSICAL_NETWORK --tenant_id $TENANT_ID --provider:network_type $PROVIDER_NETWORK_TYPE --provider:physical_network "$PHYSICAL_NETWORK" ${SEGMENTATION_ID:+--provider:segmentation_id $SEGMENTATION_ID} --shared | grep ' id ' | get_field 2)
-        SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
-        SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode slaac --gateway $V6_NETWORK_GATEWAY --name $PROVIDER_SUBNET_NAME_V6 $NET_ID $FIXED_RANGE_V6 | grep 'id' | get_field 2)
+
+        if [[ "$IP_VERSION" =~ 4.* ]]; then
+            SUBNET_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 4 ${ALLOCATION_POOL:+--allocation-pool $ALLOCATION_POOL} --name $PROVIDER_SUBNET_NAME --gateway $NETWORK_GATEWAY $NET_ID $FIXED_RANGE | grep ' id ' | get_field 2)
+        fi
+
+        if [[ "$IP_VERSION" =~ .*6 ]]; then
+            SUBNET_V6_ID=$(neutron subnet-create --tenant_id $TENANT_ID --ip_version 6 --ipv6-address-mode slaac --gateway $V6_NETWORK_GATEWAY --name $PROVIDER_SUBNET_NAME_V6 $NET_ID $FIXED_RANGE_V6 | grep 'id' | get_field 2)
+        fi
+
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
         sudo ip link set $PUBLIC_INTERFACE up
@@ -592,7 +604,7 @@
 
 # init_neutron() - Initialize databases, etc.
 function init_neutron {
-    recreate_database $Q_DB_NAME utf8
+    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
@@ -699,7 +711,7 @@
     run_process q-dhcp "python $AGENT_DHCP_BINARY --config-file $NEUTRON_CONF --config-file=$Q_DHCP_CONF_FILE"
 
     if is_provider_network; then
-        sudo ovs-vsctl add-port $OVS_PHYSICAL_BRIDGE $PUBLIC_INTERFACE
+        sudo ovs-vsctl --no-wait -- --may-exist add-port $OVS_PHYSICAL_BRIDGE $PUBLIC_INTERFACE
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
         sudo ip link set $PUBLIC_INTERFACE up
@@ -837,6 +849,9 @@
     # Format logging
     if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
         setup_colorized_logging $NEUTRON_CONF DEFAULT project_id
+    else
+        # Show user_name and project_name by default like in nova
+        iniset $NEUTRON_CONF DEFAULT logging_context_format_string "%(asctime)s.%(msecs)03d %(levelname)s %(name)s [%(request_id)s %(user_name)s %(project_name)s] %(instance)s%(message)s"
     fi
 
     if is_service_enabled tls-proxy; then
@@ -908,7 +923,7 @@
     Q_L3_ROUTER_PER_TENANT=$Q_USE_NAMESPACE
 
     if is_service_enabled q-vpn; then
-        cp $NEUTRON_DIR/etc/vpn_agent.ini $Q_VPN_CONF_FILE
+        cp $NEUTRON_VPNAAS_DIR/etc/vpn_agent.ini $Q_VPN_CONF_FILE
     fi
 
     cp $NEUTRON_DIR/etc/l3_agent.ini $Q_L3_CONF_FILE
@@ -1035,22 +1050,28 @@
     fi
 }
 
+# _neutron_deploy_rootwrap_filters() - deploy rootwrap filters to $Q_CONF_ROOTWRAP_D (owned by root).
+function _neutron_deploy_rootwrap_filters {
+    local srcdir=$1
+    mkdir -p -m 755 $Q_CONF_ROOTWRAP_D
+    sudo cp -pr $srcdir/etc/neutron/rootwrap.d/* $Q_CONF_ROOTWRAP_D/
+    sudo chown -R root:root $Q_CONF_ROOTWRAP_D
+    sudo chmod 644 $Q_CONF_ROOTWRAP_D/*
+}
+
 # _neutron_setup_rootwrap() - configure Neutron's rootwrap
 function _neutron_setup_rootwrap {
     if [[ "$Q_USE_ROOTWRAP" == "False" ]]; then
         return
     fi
-    # Deploy new rootwrap filters files (owned by root).
     # Wipe any existing ``rootwrap.d`` files first
     Q_CONF_ROOTWRAP_D=$NEUTRON_CONF_DIR/rootwrap.d
     if [[ -d $Q_CONF_ROOTWRAP_D ]]; then
         sudo rm -rf $Q_CONF_ROOTWRAP_D
     fi
-    # Deploy filters to ``$NEUTRON_CONF_DIR/rootwrap.d``
-    mkdir -p -m 755 $Q_CONF_ROOTWRAP_D
-    cp -pr $NEUTRON_DIR/etc/neutron/rootwrap.d/* $Q_CONF_ROOTWRAP_D/
-    sudo chown -R root:root $Q_CONF_ROOTWRAP_D
-    sudo chmod 644 $Q_CONF_ROOTWRAP_D/*
+
+    _neutron_deploy_rootwrap_filters $NEUTRON_DIR
+
     # Set up ``rootwrap.conf``, pointing to ``$NEUTRON_CONF_DIR/rootwrap.d``
     # location moved in newer versions, prefer new location
     if test -r $NEUTRON_DIR/etc/neutron/rootwrap.conf; then
diff --git a/lib/neutron_plugins/cisco b/lib/neutron_plugins/cisco
index b067aa6..90dcd57 100644
--- a/lib/neutron_plugins/cisco
+++ b/lib/neutron_plugins/cisco
@@ -144,6 +144,10 @@
     fi
 }
 
+function neutron_plugin_create_initial_network_profile {
+    neutron cisco-network-profile-create default_network_profile vlan --segment_range 1-3000 --physical_network "$1"
+}
+
 function neutron_plugin_setup_interface_driver {
     local conf_file=$1
     iniset $conf_file DEFAULT interface_driver neutron.agent.linux.interface.OVSInterfaceDriver
diff --git a/lib/neutron_plugins/midonet b/lib/neutron_plugins/midonet
index eb27ed6..23ad8b2 100644
--- a/lib/neutron_plugins/midonet
+++ b/lib/neutron_plugins/midonet
@@ -29,6 +29,18 @@
     Q_PLUGIN_CONF_PATH=etc/neutron/plugins/midonet
     Q_PLUGIN_CONF_FILENAME=midonet.ini
     Q_PLUGIN_CLASS="neutron.plugins.midonet.plugin.MidonetPluginV2"
+
+    # MidoNet implements LBaaS API in the plugin, not as an LBaaS driver.
+    # In this model, the plugin references the 'neutron_lbaas' module but
+    # does not require starting an LBaaS service.  Devstack, however, clones
+    # 'neutron_lbaas' only if 'lbaas' service is enabled.  To get around this,
+    # always clone 'neutron_lbaas' so that it is made available to the plugin.
+    # Also, discontinue if the 'lbaas' service is enabled.
+    if is_service_enabled q-lbaas; then
+        die $LINENO "LBaaS service should be disabled for the MidoNet plugin"
+    fi
+    git_clone $NEUTRON_LBAAS_REPO $NEUTRON_LBAAS_DIR $NEUTRON_LBAAS_BRANCH
+    setup_develop $NEUTRON_LBAAS_DIR
 }
 
 function neutron_plugin_configure_debug_command {
diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall
index a1c13ed..61a148e 100644
--- a/lib/neutron_plugins/services/firewall
+++ b/lib/neutron_plugins/services/firewall
@@ -13,7 +13,7 @@
 
 function neutron_fwaas_configure_driver {
     FWAAS_DRIVER_CONF_FILENAME=/etc/neutron/fwaas_driver.ini
-    cp $NEUTRON_DIR/etc/fwaas_driver.ini $FWAAS_DRIVER_CONF_FILENAME
+    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini $FWAAS_DRIVER_CONF_FILENAME
 
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas enabled True
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver"
diff --git a/lib/neutron_plugins/services/loadbalancer b/lib/neutron_plugins/services/loadbalancer
index bd9dc87..f465cc9 100644
--- a/lib/neutron_plugins/services/loadbalancer
+++ b/lib/neutron_plugins/services/loadbalancer
@@ -17,6 +17,7 @@
 
 function neutron_agent_lbaas_configure_common {
     _neutron_service_plugin_class_add $LBAAS_PLUGIN
+    _neutron_deploy_rootwrap_filters $NEUTRON_LBAAS_DIR
 }
 
 function neutron_agent_lbaas_configure_agent {
@@ -25,7 +26,7 @@
 
     LBAAS_AGENT_CONF_FILENAME="$LBAAS_AGENT_CONF_PATH/lbaas_agent.ini"
 
-    cp $NEUTRON_DIR/etc/lbaas_agent.ini $LBAAS_AGENT_CONF_FILENAME
+    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini $LBAAS_AGENT_CONF_FILENAME
 
     # ovs_use_veth needs to be set before the plugin configuration
     # occurs to allow plugins to override the setting.
diff --git a/lib/neutron_plugins/services/vpn b/lib/neutron_plugins/services/vpn
index 07f1f35..7e80b5b 100644
--- a/lib/neutron_plugins/services/vpn
+++ b/lib/neutron_plugins/services/vpn
@@ -16,6 +16,7 @@
 
 function neutron_vpn_configure_common {
     _neutron_service_plugin_class_add $VPN_PLUGIN
+    _neutron_deploy_rootwrap_filters $NEUTRON_VPNAAS_DIR
 }
 
 function neutron_vpn_stop {
diff --git a/lib/nova b/lib/nova
index cbfbdfa..76212ed 100644
--- a/lib/nova
+++ b/lib/nova
@@ -106,7 +106,7 @@
 
 # $NOVA_VNC_ENABLED can be used to forcibly enable vnc configuration.
 # In multi-node setups allows compute hosts to not run n-novnc.
-NOVA_VNC_ENABLED=$(trueorfalse False $NOVA_VNC_ENABLED)
+NOVA_VNC_ENABLED=$(trueorfalse False NOVA_VNC_ENABLED)
 
 # Get hypervisor configuration
 # ----------------------------
@@ -145,11 +145,11 @@
 # ``MULTI_HOST`` is a mode where each compute node runs its own network node.  This
 # allows network operations and routing for a VM to occur on the server that is
 # running the VM - removing a SPOF and bandwidth bottleneck.
-MULTI_HOST=`trueorfalse False $MULTI_HOST`
+MULTI_HOST=$(trueorfalse False MULTI_HOST)
 
 # ``NOVA_ALLOW_MOVE_TO_SAME_HOST` can be set to False in multi node devstack,
 # where there are at least two nova-computes.
-NOVA_ALLOW_MOVE_TO_SAME_HOST=`trueorfalse True $NOVA_ALLOW_MOVE_TO_SAME_HOST`
+NOVA_ALLOW_MOVE_TO_SAME_HOST=$(trueorfalse True NOVA_ALLOW_MOVE_TO_SAME_HOST)
 
 # Test floating pool and range are used for testing.  They are defined
 # here until the admin APIs can replace nova-manage
@@ -547,6 +547,11 @@
     iniset $NOVA_CONF DEFAULT ec2_workers "$API_WORKERS"
     iniset $NOVA_CONF DEFAULT metadata_workers "$API_WORKERS"
 
+    if [[ "$NOVA_BACKEND" == "LVM" ]]; then
+        iniset $NOVA_CONF libvirt images_type "lvm"
+        iniset $NOVA_CONF libvirt images_volume_group $DEFAULT_VOLUME_GROUP_NAME
+    fi
+
     if is_ssl_enabled_service glance || is_service_enabled tls-proxy; then
         iniset $NOVA_CONF DEFAULT glance_protocol https
     fi
@@ -623,16 +628,13 @@
     # Only do this step once on the API node for an entire cluster.
     if is_service_enabled $DATABASE_BACKENDS && is_service_enabled n-api; then
         # (Re)create nova database
-        # Explicitly use latin1: to avoid lp#829209, nova expects the database to
-        # use latin1 by default, and then upgrades the database to utf8 (see the
-        # 082_essex.py in nova)
-        recreate_database nova latin1
+        recreate_database nova
 
         # Migrate nova database
         $NOVA_BIN_DIR/nova-manage db sync
 
         if is_service_enabled n-cell; then
-            recreate_database $NOVA_CELLS_DB latin1
+            recreate_database $NOVA_CELLS_DB
         fi
     fi
 
@@ -657,7 +659,7 @@
 
     if is_service_enabled n-novnc; then
         # a websockets/html5 or flash powered VNC console for vm instances
-        NOVNC_FROM_PACKAGE=`trueorfalse False $NOVNC_FROM_PACKAGE`
+        NOVNC_FROM_PACKAGE=$(trueorfalse False NOVNC_FROM_PACKAGE)
         if [ "$NOVNC_FROM_PACKAGE" = "True" ]; then
             NOVNC_WEB_DIR=/usr/share/novnc
             install_package novnc
@@ -669,7 +671,7 @@
 
     if is_service_enabled n-spice; then
         # a websockets/html5 or flash powered SPICE console for vm instances
-        SPICE_FROM_PACKAGE=`trueorfalse True $SPICE_FROM_PACKAGE`
+        SPICE_FROM_PACKAGE=$(trueorfalse True SPICE_FROM_PACKAGE)
         if [ "$SPICE_FROM_PACKAGE" = "True" ]; then
             SPICE_WEB_DIR=/usr/share/spice-html5
             install_package spice-html5
@@ -769,8 +771,8 @@
 }
 
 function start_nova {
-    start_nova_compute
     start_nova_rest
+    start_nova_compute
 }
 
 function stop_nova_compute {
diff --git a/lib/nova_plugins/functions-libvirt b/lib/nova_plugins/functions-libvirt
index 4601eea..4d617e8 100644
--- a/lib/nova_plugins/functions-libvirt
+++ b/lib/nova_plugins/functions-libvirt
@@ -15,7 +15,7 @@
 # --------
 
 # if we should turn on massive libvirt debugging
-DEBUG_LIBVIRT=$(trueorfalse False $DEBUG_LIBVIRT)
+DEBUG_LIBVIRT=$(trueorfalse False DEBUG_LIBVIRT)
 
 # Installs required distro-specific libvirt packages.
 function install_libvirt {
@@ -37,8 +37,7 @@
 
     # Note there is a difference between F20 rackspace cloud images
     # and HP images used in the gate; rackspace has firewalld but hp
-    # cloud doesn't.  RHEL6 doesn't have firewalld either.  So we
-    # don't care if it fails.
+    # cloud doesn't.
     if is_fedora && is_package_installed firewalld; then
         sudo service firewalld restart || true
     fi
@@ -68,34 +67,12 @@
     fi
 
     if is_fedora || is_suse; then
-        if is_fedora && [[ $DISTRO =~ (rhel6) || "$os_RELEASE" -le "17" ]]; then
-            cat <<EOF | sudo tee /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla
-[libvirt Management Access]
-Identity=unix-group:$LIBVIRT_GROUP
-Action=org.libvirt.unix.manage
-ResultAny=yes
-ResultInactive=yes
-ResultActive=yes
-EOF
-        elif is_suse && [[ $os_RELEASE = 12.2 || "$os_VENDOR" = "SUSE LINUX" ]]; then
-            # openSUSE < 12.3 or SLE
-            # Work around the fact that polkit-default-privs overrules pklas
-            # with 'unix-group:$group'.
-            cat <<EOF | sudo tee /etc/polkit-1/localauthority/50-local.d/50-libvirt-remote-access.pkla
-[libvirt Management Access]
-Identity=unix-user:$STACK_USER
-Action=org.libvirt.unix.manage
-ResultAny=yes
-ResultInactive=yes
-ResultActive=yes
-EOF
-        else
-            # Starting with fedora 18 and opensuse-12.3 enable stack-user to
-            # virsh -c qemu:///system by creating a policy-kit rule for
-            # stack-user using the new Javascript syntax
-            rules_dir=/etc/polkit-1/rules.d
-            sudo mkdir -p $rules_dir
-            cat <<EOF | sudo tee $rules_dir/50-libvirt-$STACK_USER.rules
+        # Starting with fedora 18 and opensuse-12.3 enable stack-user to
+        # virsh -c qemu:///system by creating a policy-kit rule for
+        # stack-user using the new Javascript syntax
+        rules_dir=/etc/polkit-1/rules.d
+        sudo mkdir -p $rules_dir
+        cat <<EOF | sudo tee $rules_dir/50-libvirt-$STACK_USER.rules
 polkit.addRule(function(action, subject) {
     if (action.id == 'org.libvirt.unix.manage' &&
         subject.user == '$STACK_USER') {
@@ -103,8 +80,7 @@
     }
 });
 EOF
-            unset rules_dir
-        fi
+        unset rules_dir
     fi
 
     # The user that nova runs as needs to be member of **libvirtd** group otherwise
diff --git a/lib/nova_plugins/hypervisor-ironic b/lib/nova_plugins/hypervisor-ironic
index 4c2043b..0169d73 100644
--- a/lib/nova_plugins/hypervisor-ironic
+++ b/lib/nova_plugins/hypervisor-ironic
@@ -56,6 +56,8 @@
 function install_nova_hypervisor {
     if ! is_service_enabled neutron; then
         die $LINENO "Neutron should be enabled for usage of the Ironic Nova driver."
+    elif is_ironic_hardware; then
+        return
     fi
     install_libvirt
     if [[ "$IRONIC_VM_LOG_CONSOLE" == "True" ]] && is_ubuntu; then
diff --git a/lib/nova_plugins/hypervisor-libvirt b/lib/nova_plugins/hypervisor-libvirt
index b1b4400..4d1eb6c 100644
--- a/lib/nova_plugins/hypervisor-libvirt
+++ b/lib/nova_plugins/hypervisor-libvirt
@@ -54,7 +54,7 @@
         iniset $NOVA_CONF DEFAULT vnc_enabled "false"
     fi
 
-    ENABLE_FILE_INJECTION=$(trueorfalse False $ENABLE_FILE_INJECTION)
+    ENABLE_FILE_INJECTION=$(trueorfalse False ENABLE_FILE_INJECTION)
     if [[ "$ENABLE_FILE_INJECTION" = "True" ]] ; then
         # When libguestfs is available for file injection, enable using
         # libguestfs to inspect the image and figure out the proper
diff --git a/lib/rpc_backend b/lib/rpc_backend
index 172d024..98be184 100644
--- a/lib/rpc_backend
+++ b/lib/rpc_backend
@@ -21,6 +21,11 @@
 XTRACE=$(set +o | grep xtrace)
 set +o xtrace
 
+RPC_MESSAGING_PROTOCOL=${RPC_MESSAGING_PROTOCOL:-0.9}
+
+# TODO(sdague): RPC backend selection is super wonky because we treat
+# messaging server as a service, which it really isn't for multi host
+QPID_HOST=${QPID_HOST:-}
 
 # Functions
 # ---------
@@ -49,13 +54,15 @@
         (( rpc_backend_cnt++ )) || true
     done
     if [ "$rpc_backend_cnt" -gt 1 ]; then
-        echo "ERROR: only one rpc backend may be enabled,"
-        echo "       set only one of 'rabbit', 'qpid', 'zeromq'"
-        echo "       via ENABLED_SERVICES."
+        die $LINENO \
+            "Only one rpc backend may be enabled, " \
+            "set only one of 'rabbit', 'qpid', 'zeromq' " \
+            "via ENABLED_SERVICES."
     elif [ "$rpc_backend_cnt" == 0 ] && [ "$rpc_needed" == 0 ]; then
-        echo "ERROR: at least one rpc backend must be enabled,"
-        echo "       set one of 'rabbit', 'qpid', 'zeromq'"
-        echo "       via ENABLED_SERVICES."
+        die $LINENO \
+            "at least one rpc backend must be enabled, " \
+            "set one of 'rabbit', 'qpid', 'zeromq'" \
+            "via ENABLED_SERVICES."
     fi
 
     if is_service_enabled qpid && ! qpid_is_supported; then
@@ -68,9 +75,6 @@
 function cleanup_rpc_backend {
     if is_service_enabled rabbit; then
         # Obliterate rabbitmq-server
-        if [ -n "$RABBIT_USERID" ]; then
-            sudo rabbitmqctl delete_user "$RABBIT_USERID"
-        fi
         uninstall_package rabbitmq-server
         sudo killall epmd || sudo killall -9 epmd
         if is_ubuntu; then
@@ -87,11 +91,20 @@
         fi
     elif is_service_enabled zeromq; then
         if is_fedora; then
-            uninstall_package zeromq python-zmq redis
+            uninstall_package zeromq python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis python-redis
+            fi
         elif is_ubuntu; then
-            uninstall_package libzmq1 python-zmq redis-server
+            uninstall_package libzmq1 python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis-server python-redis
+            fi
         elif is_suse; then
-            uninstall_package libzmq1 python-pyzmq redis
+            uninstall_package libzmq1 python-pyzmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                uninstall_package redis python-redis
+            fi
         else
             exit_distro_not_supported "zeromq installation"
         fi
@@ -150,11 +163,20 @@
         # but there is a matchmaker driver that works
         # really well & out of the box for multi-node.
         if is_fedora; then
-            install_package zeromq python-zmq redis
+            install_package zeromq python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis python-redis
+            fi
         elif is_ubuntu; then
-            install_package libzmq1 python-zmq redis-server
+            install_package libzmq1 python-zmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis-server python-redis
+            fi
         elif is_suse; then
-            install_package libzmq1 python-pyzmq redis
+            install_package libzmq1 python-pyzmq
+            if [ "$ZEROMQ_MATCHMAKER" == "redis" ]; then
+                install_package redis python-redis
+            fi
         else
             exit_distro_not_supported "zeromq installation"
         fi
diff --git a/lib/sahara b/lib/sahara
index c902d38..995935a 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -11,6 +11,7 @@
 # install_sahara
 # install_python_saharaclient
 # configure_sahara
+# sahara_register_images
 # start_sahara
 # stop_sahara
 # cleanup_sahara
@@ -128,6 +129,9 @@
     if is_service_enabled neutron; then
         iniset $SAHARA_CONF_FILE DEFAULT use_neutron true
         iniset $SAHARA_CONF_FILE DEFAULT use_floating_ips true
+    else
+        iniset $SAHARA_CONF_FILE DEFAULT use_neutron false
+        iniset $SAHARA_CONF_FILE DEFAULT use_floating_ips false
     fi
 
     if is_service_enabled heat; then
@@ -143,7 +147,7 @@
         setup_colorized_logging $SAHARA_CONF_FILE DEFAULT
     fi
 
-    recreate_database sahara utf8
+    recreate_database sahara
     $SAHARA_BIN_DIR/sahara-db-manage --config-file $SAHARA_CONF_FILE upgrade head
 }
 
@@ -161,6 +165,17 @@
     fi
 }
 
+# sahara_register_images() - Registers images in sahara image registry
+function sahara_register_images {
+    if is_service_enabled heat && [[ ! -z "$HEAT_CFN_IMAGE_URL" ]]; then
+        # Register heat image for Fake plugin
+        local fake_plugin_properties="--property _sahara_tag_0.1=True"
+        fake_plugin_properties+=" --property _sahara_tag_fake=True"
+        fake_plugin_properties+=" --property _sahara_username=fedora"
+        openstack --os-url $GLANCE_SERVICE_PROTOCOL://$GLANCE_HOSTPORT image set $(basename "$HEAT_CFN_IMAGE_URL" ".qcow2") $fake_plugin_properties
+    fi
+}
+
 # start_sahara() - Start running processes, including screen
 function start_sahara {
     run_process sahara "$SAHARA_BIN_DIR/sahara-all --config-file $SAHARA_CONF_FILE"
diff --git a/lib/swift b/lib/swift
index e9043b3..ee4543c 100644
--- a/lib/swift
+++ b/lib/swift
@@ -82,7 +82,7 @@
 
 # Set ``SWIFT_EXTRAS_MIDDLEWARE_LAST`` to extras middlewares that need to be at
 # the end of the pipeline.
-SWIFT_EXTRAS_MIDDLEWARE_LAST=${SWIFT_EXTRAS_MIDDLEWARE_LAST}
+SWIFT_EXTRAS_MIDDLEWARE_LAST=${SWIFT_EXTRAS_MIDDLEWARE_LAST:-}
 
 # Set ``SWIFT_EXTRAS_MIDDLEWARE_NO_AUTH`` to extras middlewares that need to be at
 # the beginning of the pipeline, before authentication middlewares.
@@ -127,7 +127,7 @@
 
 # Enable tempurl feature
 SWIFT_ENABLE_TEMPURLS=${SWIFT_ENABLE_TEMPURLS:-False}
-SWIFT_TEMPURL_KEY=${SWIFT_TEMPURL_KEY}
+SWIFT_TEMPURL_KEY=${SWIFT_TEMPURL_KEY:-}
 
 # Tell Tempest this project is present
 TEMPEST_SERVICES+=,swift
@@ -401,11 +401,10 @@
     sed -i "/^pipeline/ { s/tempauth/${swift_pipeline} ${SWIFT_EXTRAS_MIDDLEWARE}/ ;}" ${SWIFT_CONFIG_PROXY_SERVER}
     sed -i "/^pipeline/ { s/proxy-server/${SWIFT_EXTRAS_MIDDLEWARE_LAST} proxy-server/ ; }" ${SWIFT_CONFIG_PROXY_SERVER}
 
-    iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth account_autocreate
+
     iniset ${SWIFT_CONFIG_PROXY_SERVER} app:proxy-server account_autocreate true
 
-    iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix
-    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix "TEMPAUTH"
+
 
     # Configure Crossdomain
     iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:crossdomain use "egg:swift#crossdomain"
@@ -422,6 +421,13 @@
     iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:keystoneauth operator_roles
     iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:keystoneauth operator_roles "Member, admin"
 
+    # Configure Tempauth. In the sample config file, Keystoneauth is commented
+    # out. Make sure we uncomment Tempauth after we uncomment Keystoneauth
+    # otherwise, this code also sets the reseller_prefix for Keystoneauth.
+    iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth account_autocreate
+    iniuncomment ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix
+    iniset ${SWIFT_CONFIG_PROXY_SERVER} filter:tempauth reseller_prefix "TEMPAUTH"
+
     if is_service_enabled swift3; then
         cat <<EOF >>${SWIFT_CONFIG_PROXY_SERVER}
 # NOTE(chmou): s3token middleware is not updated yet to use only
diff --git a/lib/tempest b/lib/tempest
index d31119b..1ae9457 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -75,8 +75,8 @@
 TEMPEST_STORAGE_PROTOCOL=${TEMPEST_STORAGE_PROTOCOL:-$TEMPEST_DEFAULT_STORAGE_PROTOCOL}
 
 # Neutron/Network variables
-IPV6_ENABLED=$(trueorfalse True $IPV6_ENABLED)
-IPV6_SUBNET_ATTRIBUTES_ENABLED=$(trueorfalse True $IPV6_SUBNET_ATTRIBUTES_ENABLED)
+IPV6_ENABLED=$(trueorfalse True IPV6_ENABLED)
+IPV6_SUBNET_ATTRIBUTES_ENABLED=$(trueorfalse True IPV6_SUBNET_ATTRIBUTES_ENABLED)
 
 # Functions
 # ---------
@@ -278,7 +278,7 @@
 
     # Identity
     iniset $TEMPEST_CONFIG identity uri "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v2.0/"
-    iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_PROTOCOL://$KEYSTONE_SERVICE_HOST:5000/v3/"
+    iniset $TEMPEST_CONFIG identity uri_v3 "$KEYSTONE_SERVICE_URI_V3"
     iniset $TEMPEST_CONFIG identity username $TEMPEST_USERNAME
     iniset $TEMPEST_CONFIG identity password "$password"
     iniset $TEMPEST_CONFIG identity tenant_name $TEMPEST_TENANT_NAME
diff --git a/lib/trove b/lib/trove
index abf4e87..3249ce0 100644
--- a/lib/trove
+++ b/lib/trove
@@ -199,7 +199,7 @@
 # init_trove() - Initializes Trove Database as a Service
 function init_trove {
     # (Re)Create trove db
-    recreate_database trove utf8
+    recreate_database trove
 
     # Initialize the trove database
     $TROVE_BIN_DIR/trove-manage db_sync
diff --git a/lib/zaqar b/lib/zaqar
index 0d1f6f4..dfa3452 100644
--- a/lib/zaqar
+++ b/lib/zaqar
@@ -135,6 +135,12 @@
         configure_redis
     fi
 
+    if is_service_enabled qpid || [ -n "$RABBIT_HOST" ] && [ -n "$RABBIT_PASSWORD" ]; then
+        iniset $ZAQAR_CONF DEFAULT notification_driver messaging
+        iniset $ZAQAR_CONF DEFAULT control_exchange zaqar
+    fi
+    iniset_rpc_backend zaqar $ZAQAR_CONF DEFAULT
+
     cleanup_zaqar
 }
 
diff --git a/stack.sh b/stack.sh
index b064c22..5b56972 100755
--- a/stack.sh
+++ b/stack.sh
@@ -40,6 +40,12 @@
 # Keep track of the devstack directory
 TOP_DIR=$(cd $(dirname "$0") && pwd)
 
+# Check for uninitialized variables, a big cause of bugs
+NOUNSET=${NOUNSET:-}
+if [[ -n "$NOUNSET" ]]; then
+    set -o nounset
+fi
+
 # Sanity Checks
 # -------------
 
@@ -79,6 +85,9 @@
 # Prepare the environment
 # -----------------------
 
+# Initialize variables:
+LAST_SPINNER_PID=""
+
 # Import common functions
 source $TOP_DIR/functions
 
@@ -143,7 +152,7 @@
 
 # Warn users who aren't on an explicitly supported distro, but allow them to
 # override check and attempt installation with ``FORCE=yes ./stack``
-if [[ ! ${DISTRO} =~ (precise|trusty|7.0|wheezy|sid|testing|jessie|f19|f20|f21|rhel6|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (precise|trusty|7.0|wheezy|sid|testing|jessie|f20|f21|rhel7) ]]; then
     echo "WARNING: this script has not been tested on $DISTRO"
     if [[ "$FORCE" != "yes" ]]; then
         die $LINENO "If you wish to run this script anyway run with FORCE=yes"
@@ -172,12 +181,12 @@
 disable_negated_services
 
 # Look for obsolete stuff
-if [[ ,${ENABLED_SERVICES}, =~ ,"swift", ]]; then
-    echo "FATAL: 'swift' is not supported as a service name"
-    echo "FATAL: Use the actual swift service names to enable them as required:"
-    echo "FATAL: s-proxy s-object s-container s-account"
-    exit 1
-fi
+# if [[ ,${ENABLED_SERVICES}, =~ ,"swift", ]]; then
+#     echo "FATAL: 'swift' is not supported as a service name"
+#     echo "FATAL: Use the actual swift service names to enable them as required:"
+#     echo "FATAL: s-proxy s-object s-container s-account"
+#     exit 1
+# fi
 
 # Configure sudo
 # --------------
@@ -212,7 +221,7 @@
 # Some distros need to add repos beyond the defaults provided by the vendor
 # to pick up required packages.
 
-if is_fedora && [[ $DISTRO == "rhel6" || $DISTRO == "rhel7" ]]; then
+if is_fedora && [[ $DISTRO == "rhel7" ]]; then
     # RHEL requires EPEL for many Open Stack dependencies
 
     # note we always remove and install latest -- some environments
@@ -230,16 +239,10 @@
     # $releasever directly in .repo file we create below.  However
     # RHEL gives a $releasever of "6Server" which breaks the path;
     # see https://bugzilla.redhat.com/show_bug.cgi?id=1150759
-    if [[ $DISTRO == "rhel7" ]]; then
-        epel_ver="7"
-    elif [[ $DISTRO == "rhel6" ]]; then
-        epel_ver="6"
-    fi
-
     cat <<EOF | sudo tee /etc/yum.repos.d/epel-bootstrap.repo
 [epel-bootstrap]
 name=Bootstrap EPEL
-mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-$epel_ver&arch=\$basearch
+mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-7&arch=\$basearch
 failovermethod=priority
 enabled=0
 gpgcheck=0
@@ -252,22 +255,10 @@
 
     # ... and also optional to be enabled
     is_package_installed yum-utils || install_package yum-utils
-    if [[ $DISTRO == "rhel7" ]]; then
-        OPTIONAL_REPO=rhel-7-server-optional-rpms
-    elif [[ $DISTRO == "rhel6" ]]; then
-        OPTIONAL_REPO=rhel-6-server-optional-rpms
-    fi
-    sudo yum-config-manager --enable ${OPTIONAL_REPO}
+    sudo yum-config-manager --enable rhel-7-server-optional-rpms
 
-    # Installing Open vSwitch on RHEL requires enabling the RDO repo.
-    # Note no juno packages for rhel6
-    if [[ $DISTRO == "rhel6" ]]; then
-        RHEL_RDO_REPO_RPM=${RHEL6_RDO_REPO_RPM:-"https://repos.fedorapeople.org/repos/openstack/openstack-icehouse/rdo-release-icehouse-4.noarch.rpm"}
-        RHEL_RDO_REPO_ID=${RHEL6_RDO_REPO_ID:-"openstack-icehouse"}
-    elif [[ $DISTRO == "rhel7" ]]; then
-        RHEL_RDO_REPO_RPM=${RHEL7_RDO_REPO_RPM:-"https://repos.fedorapeople.org/repos/openstack/openstack-juno/rdo-release-juno-1.noarch.rpm"}
-        RHEL_RDO_REPO_ID=${RHEL7_RDO_REPO_ID:-"openstack-juno"}
-    fi
+    RHEL_RDO_REPO_RPM=${RHEL7_RDO_REPO_RPM:-"https://repos.fedorapeople.org/repos/openstack/openstack-juno/rdo-release-juno-1.noarch.rpm"}
+    RHEL_RDO_REPO_ID=${RHEL7_RDO_REPO_ID:-"openstack-juno"}
 
     if ! sudo yum repolist enabled $RHEL_RDO_REPO_ID | grep -q $RHEL_RDO_REPO_ID; then
         echo "RDO repo not detected; installing"
@@ -311,7 +302,7 @@
 # -----------------
 
 # Set up logging level
-VERBOSE=$(trueorfalse True $VERBOSE)
+VERBOSE=$(trueorfalse True VERBOSE)
 
 # Draw a spinner so the user knows something is happening
 function spinner {
@@ -353,32 +344,23 @@
     echo $@ >&3
 }
 
-if is_fedora && [ $DISTRO == "rhel6" ]; then
-    # poor old python2.6 doesn't have argparse by default, which
-    # outfilter.py uses
-    is_package_installed python-argparse || install_package python-argparse
-fi
-
 # Set up logging for ``stack.sh``
 # Set ``LOGFILE`` to turn on logging
 # Append '.xxxxxxxx' to the given name to maintain history
 # where 'xxxxxxxx' is a representation of the date the file was created
 TIMESTAMP_FORMAT=${TIMESTAMP_FORMAT:-"%F-%H%M%S"}
-if [[ -n "$LOGFILE" || -n "$SCREEN_LOGDIR" ]]; then
-    LOGDAYS=${LOGDAYS:-7}
-    CURRENT_LOG_TIME=$(date "+$TIMESTAMP_FORMAT")
-fi
+LOGDAYS=${LOGDAYS:-7}
+CURRENT_LOG_TIME=$(date "+$TIMESTAMP_FORMAT")
 
 if [[ -n "$LOGFILE" ]]; then
-    # First clean up old log files.  Use the user-specified ``LOGFILE``
-    # as the template to search for, appending '.*' to match the date
-    # we added on earlier runs.
-    LOGDIR=$(dirname "$LOGFILE")
-    LOGFILENAME=$(basename "$LOGFILE")
-    mkdir -p $LOGDIR
-    find $LOGDIR -maxdepth 1 -name $LOGFILENAME.\* -mtime +$LOGDAYS -exec rm {} \;
+    # Clean up old log files.  Append '.*' to the user-specified
+    # ``LOGFILE`` to match the date in the search template.
+    LOGFILE_DIR="${LOGFILE%/*}"           # dirname
+    LOGFILE_NAME="${LOGFILE##*/}"         # basename
+    mkdir -p $LOGFILE_DIR
+    find $LOGFILE_DIR -maxdepth 1 -name $LOGFILE_NAME.\* -mtime +$LOGDAYS -exec rm {} \;
     LOGFILE=$LOGFILE.${CURRENT_LOG_TIME}
-    SUMFILE=$LOGFILE.${CURRENT_LOG_TIME}.summary
+    SUMFILE=$LOGFILE.summary.${CURRENT_LOG_TIME}
 
     # Redirect output according to config
 
@@ -399,8 +381,8 @@
 
     echo_summary "stack.sh log $LOGFILE"
     # Specified logfile name always links to the most recent log
-    ln -sf $LOGFILE $LOGDIR/$LOGFILENAME
-    ln -sf $SUMFILE $LOGDIR/$LOGFILENAME.summary
+    ln -sf $LOGFILE $LOGFILE_DIR/$LOGFILE_NAME
+    ln -sf $SUMFILE $LOGFILE_DIR/$LOGFILE_NAME.summary
 else
     # Set up output redirection without log files
     # Set fd 3 to a copy of stdout. So we can set fd 1 without losing
@@ -420,6 +402,7 @@
 # ``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``.
+# This is deprecated....logs go in ``LOGDIR``, only symlinks will be here now.
 if [[ -n "$SCREEN_LOGDIR" ]]; then
 
     # We make sure the directory is created.
@@ -482,47 +465,6 @@
 # an error.  It is also useful for following along as the install occurs.
 set -o xtrace
 
-
-# Common Configuration
-# --------------------
-
-# Set ``OFFLINE`` to ``True`` to configure ``stack.sh`` to run cleanly without
-# Internet access. ``stack.sh`` must have been previously run with Internet
-# access to install prerequisites and fetch repositories.
-OFFLINE=`trueorfalse False $OFFLINE`
-
-# Set ``ERROR_ON_CLONE`` to ``True`` to configure ``stack.sh`` to exit if
-# the destination git repository does not exist during the ``git_clone``
-# operation.
-ERROR_ON_CLONE=`trueorfalse False $ERROR_ON_CLONE`
-
-# Whether to enable the debug log level in OpenStack services
-ENABLE_DEBUG_LOG_LEVEL=`trueorfalse True $ENABLE_DEBUG_LOG_LEVEL`
-
-# Set fixed and floating range here so we can make sure not to use addresses
-# from either range when attempting to guess the IP to use for the host.
-# Note that setting FIXED_RANGE may be necessary when running DevStack
-# in an OpenStack cloud that uses either of these address ranges internally.
-FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.0/24}
-FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24}
-FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256}
-
-HOST_IP=$(get_default_host_ip $FIXED_RANGE $FLOATING_RANGE "$HOST_IP_IFACE" "$HOST_IP")
-if [ "$HOST_IP" == "" ]; then
-    die $LINENO "Could not determine host ip address.  See local.conf for suggestions on setting HOST_IP."
-fi
-
-# Allow the use of an alternate hostname (such as localhost/127.0.0.1) for service endpoints.
-SERVICE_HOST=${SERVICE_HOST:-$HOST_IP}
-
-# Configure services to use syslog instead of writing to individual log files
-SYSLOG=`trueorfalse False $SYSLOG`
-SYSLOG_HOST=${SYSLOG_HOST:-$HOST_IP}
-SYSLOG_PORT=${SYSLOG_PORT:-516}
-
-# Use color for logging output (only available if syslog is not used)
-LOG_COLOR=`trueorfalse True $LOG_COLOR`
-
 # Reset the bundle of CA certificates
 SSL_BUNDLE_FILE="$DATA_DIR/ca-bundle.pem"
 rm -f $SSL_BUNDLE_FILE
@@ -535,9 +477,6 @@
 # and the specified rpc backend is available on your platform.
 check_rpc_backend
 
-# Use native SSL for servers in SSL_ENABLED_SERVICES
-USE_SSL=$(trueorfalse False $USE_SSL)
-
 # Service to enable with SSL if USE_SSL is True
 SSL_ENABLED_SERVICES="key,nova,cinder,glance,s-proxy,neutron"
 
@@ -558,6 +497,7 @@
 source $TOP_DIR/lib/infra
 source $TOP_DIR/lib/oslo
 source $TOP_DIR/lib/stackforge
+source $TOP_DIR/lib/lvm
 source $TOP_DIR/lib/horizon
 source $TOP_DIR/lib/keystone
 source $TOP_DIR/lib/glance
@@ -641,7 +581,7 @@
 # The available database backends are listed in ``DATABASE_BACKENDS`` after
 # ``lib/database`` is sourced. ``mysql`` is the default.
 
-initialize_database_backends && echo "Using $DATABASE_TYPE database backend" || echo "No database enabled"
+initialize_database_backends && echo "Using $DATABASE_TYPE database backend" || die $LINENO "No database enabled"
 
 
 # Queue Configuration
@@ -708,7 +648,20 @@
 
 # Configure an appropriate python environment
 if [[ "$OFFLINE" != "True" ]]; then
-    PYPI_ALTERNATIVE_URL=$PYPI_ALTERNATIVE_URL $TOP_DIR/tools/install_pip.sh
+    PYPI_ALTERNATIVE_URL=${PYPI_ALTERNATIVE_URL:-""} $TOP_DIR/tools/install_pip.sh
+fi
+
+TRACK_DEPENDS=${TRACK_DEPENDS:-False}
+
+# Install python packages into a virtualenv so that we can track them
+if [[ $TRACK_DEPENDS = True ]]; then
+    echo_summary "Installing Python packages into a virtualenv $DEST/.venv"
+    pip_install -U virtualenv
+
+    rm -rf $DEST/.venv
+    virtualenv --system-site-packages $DEST/.venv
+    source $DEST/.venv/bin/activate
+    $DEST/.venv/bin/pip freeze > $DEST/requires-pre-pip
 fi
 
 # Do the ugly hacks for broken packages and distros
@@ -731,19 +684,6 @@
     install_neutron_agent_packages
 fi
 
-TRACK_DEPENDS=${TRACK_DEPENDS:-False}
-
-# Install python packages into a virtualenv so that we can track them
-if [[ $TRACK_DEPENDS = True ]]; then
-    echo_summary "Installing Python packages into a virtualenv $DEST/.venv"
-    pip_install -U virtualenv
-
-    rm -rf $DEST/.venv
-    virtualenv --system-site-packages $DEST/.venv
-    source $DEST/.venv/bin/activate
-    $DEST/.venv/bin/pip freeze > $DEST/requires-pre-pip
-fi
-
 # Check Out and Install Source
 # ----------------------------
 
@@ -783,7 +723,7 @@
     git_clone_by_name "python-openstackclient"
     setup_dev_lib "python-openstackclient"
 else
-    pip_install 'python-openstackclient>=1.0.0'
+    pip_install 'python-openstackclient>=1.0.2'
 fi
 
 
@@ -944,13 +884,14 @@
 # Configure screen
 # ----------------
 
-USE_SCREEN=$(trueorfalse True $USE_SCREEN)
+USE_SCREEN=$(trueorfalse True USE_SCREEN)
 if [[ "$USE_SCREEN" == "True" ]]; then
     # Create a new named screen to run processes in
     screen -d -m -S $SCREEN_NAME -t shell -s /bin/bash
     sleep 1
 
     # Set a reasonable status bar
+    SCREEN_HARDSTATUS=${SCREEN_HARDSTATUS-:}
     if [ -z "$SCREEN_HARDSTATUS" ]; then
         SCREEN_HARDSTATUS='%{= .} %-Lw%{= .}%> %n%f %t*%{= .}%+Lw%< %-=%{g}(%{d}%H/%l%{g})'
     fi
@@ -973,6 +914,10 @@
 # A better kind of sysstat, with the top process per time slice
 start_dstat
 
+# Initialize default LVM volume group
+# -----------------------------------
+init_lvm_volume_group $DEFAULT_VOLUME_GROUP_NAME $VOLUME_BACKING_FILE_SIZE
+
 # Start Services
 # ==============
 
@@ -1030,6 +975,14 @@
 fi
 
 
+# ZeroMQ
+# ------
+if is_service_enabled zeromq; then
+    echo_summary "Starting zeromq receiver"
+    run_process zeromq "$OSLO_BIN_DIR/oslo-messaging-zmq-receiver"
+fi
+
+
 # Horizon
 # -------
 
@@ -1208,11 +1161,6 @@
     iniset $NOVA_CONF keymgr fixed_key $(generate_hex_string 32)
 fi
 
-if is_service_enabled zeromq; then
-    echo_summary "Starting zermomq receiver"
-    run_process zeromq "$OSLO_BIN_DIR/oslo-messaging-zmq-receiver"
-fi
-
 # Launch the nova-api and wait for it to answer before continuing
 if is_service_enabled n-api; then
     echo_summary "Starting Nova API"
diff --git a/stackrc b/stackrc
index 355c0dc..ff82140 100644
--- a/stackrc
+++ b/stackrc
@@ -43,9 +43,17 @@
 #  enable_service q-meta
 #  # Optional, to enable tempest configuration as part of devstack
 #  enable_service tempest
+function isset {
+    local nounset=$(set +o | grep nounset)
+    set +o nounset
+    [[ -n "${!1+x}" ]]
+    result=$?
+    $nounset
+    return $result
+}
 
 # this allows us to pass ENABLED_SERVICES
-if [[ -z "$ENABLED_SERVICES" ]]; then
+if ! isset ENABLED_SERVICES ; then
     # core compute (glance / keystone / nova (+ nova-network))
     ENABLED_SERVICES=g-api,g-reg,key,n-api,n-crt,n-obj,n-cpu,n-net,n-cond,n-sch,n-xvnc,n-cauth
     # cinder
@@ -106,7 +114,7 @@
 
 # This can be used to turn database query logging on and off
 # (currently only implemented for MySQL backend)
-DATABASE_QUERY_LOGGING=$(trueorfalse True $DATABASE_QUERY_LOGGING)
+DATABASE_QUERY_LOGGING=$(trueorfalse True DATABASE_QUERY_LOGGING)
 
 # Set a timeout for git operations.  If git is still running when the
 # timeout expires, the command will be retried up to 3 times.  This is
@@ -593,7 +601,7 @@
 
 # Staging Area for New Images, have them here for at least 24hrs for nodepool
 # to cache them otherwise the failure rates in the gate are too high
-PRECACHE_IMAGES=$(trueorfalse False $PRECACHE_IMAGES)
+PRECACHE_IMAGES=$(trueorfalse False PRECACHE_IMAGES)
 if [[ "$PRECACHE_IMAGES" == "True" ]]; then
     # staging in update for nodepool
     IMAGE_URL="https://download.fedoraproject.org/pub/alt/openstack/20/x86_64/Fedora-x86_64-20-20140618-sda.qcow2"
@@ -646,8 +654,104 @@
 # till we get to the point we need to handle this automatically
 YUM=${YUM:-yum}
 
+# Common Configuration
+# --------------------
+
+# Set ``OFFLINE`` to ``True`` to configure ``stack.sh`` to run cleanly without
+# Internet access. ``stack.sh`` must have been previously run with Internet
+# access to install prerequisites and fetch repositories.
+OFFLINE=$(trueorfalse False OFFLINE)
+
+# Set ``ERROR_ON_CLONE`` to ``True`` to configure ``stack.sh`` to exit if
+# the destination git repository does not exist during the ``git_clone``
+# operation.
+ERROR_ON_CLONE=$(trueorfalse False ERROR_ON_CLONE)
+
+# Whether to enable the debug log level in OpenStack services
+ENABLE_DEBUG_LOG_LEVEL=$(trueorfalse True ENABLE_DEBUG_LOG_LEVEL)
+
+# Set fixed and floating range here so we can make sure not to use addresses
+# from either range when attempting to guess the IP to use for the host.
+# Note that setting FIXED_RANGE may be necessary when running DevStack
+# in an OpenStack cloud that uses either of these address ranges internally.
+FLOATING_RANGE=${FLOATING_RANGE:-172.24.4.0/24}
+FIXED_RANGE=${FIXED_RANGE:-10.0.0.0/24}
+FIXED_NETWORK_SIZE=${FIXED_NETWORK_SIZE:-256}
+HOST_IP_IFACE=${HOST_IP_IFACE:-}
+HOST_IP=${HOST_IP:-}
+
+HOST_IP=$(get_default_host_ip $FIXED_RANGE $FLOATING_RANGE "$HOST_IP_IFACE" "$HOST_IP")
+if [ "$HOST_IP" == "" ]; then
+    die $LINENO "Could not determine host ip address.  See local.conf for suggestions on setting HOST_IP."
+fi
+
+# Allow the use of an alternate hostname (such as localhost/127.0.0.1) for service endpoints.
+SERVICE_HOST=${SERVICE_HOST:-$HOST_IP}
+
+# Configure services to use syslog instead of writing to individual log files
+SYSLOG=$(trueorfalse False SYSLOG)
+SYSLOG_HOST=${SYSLOG_HOST:-$HOST_IP}
+SYSLOG_PORT=${SYSLOG_PORT:-516}
+
+# Use color for logging output (only available if syslog is not used)
+LOG_COLOR=$(trueorfalse True LOG_COLOR)
+
+# Set global ``GIT_DEPTH=<number>`` to limit the history depth of the git clone
+# Set to 0 to disable shallow cloning
+GIT_DEPTH=${GIT_DEPTH:-0}
+
+# Use native SSL for servers in SSL_ENABLED_SERVICES
+USE_SSL=$(trueorfalse False USE_SSL)
+
 # Following entries need to be last items in file
 
+# Compatibility bits required by other callers like Grenade
+
+# Old way was using SCREEN_LOGDIR to locate those logs and LOGFILE for the stack.sh trace log.
+# LOGFILE       SCREEN_LOGDIR       output
+# not set       not set             no log files
+# set           not set             stack.sh log to LOGFILE
+# not set       set                 screen logs to SCREEN_LOGDIR
+# set           set                 stack.sh log to LOGFILE, screen logs to SCREEN_LOGDIR
+
+# New way is LOGDIR for all logs and LOGFILE for stack.sh trace log, but if not fully-qualified will be in LOGDIR
+# LOGFILE       LOGDIR              output
+# not set       not set             (new) set LOGDIR from default
+# set           not set             stack.sh log to LOGFILE, (new) set LOGDIR from LOGFILE
+# not set       set                 screen logs to LOGDIR
+# set           set                 stack.sh log to LOGFILE, screen logs to LOGDIR
+
+# For compat, if SCREEN_LOGDIR is set, it will be used to create back-compat symlinks to the LOGDIR
+# symlinks to SCREEN_LOGDIR (compat)
+
+
+# Set up new logging defaults
+if [[ -z "${LOGDIR:-}" ]]; then
+    default_logdir=$DEST/logs
+    if [[ -z "${LOGFILE:-}" ]]; then
+        # Nothing is set, we need a default
+        LOGDIR="$default_logdir"
+    else
+        # Set default LOGDIR
+        LOGDIR="${LOGFILE%/*}"
+        logfile="${LOGFILE##*/}"
+        if [[ -z "$LOGDIR" || "$LOGDIR" == "$logfile" ]]; then
+            # LOGFILE had no path, set a default
+            LOGDIR="$default_logdir"
+        fi
+
+        # Check for duplication
+        if [[ "${SCREEN_LOGDIR:-}" == "${LOGDIR}" ]]; then
+            # We don't need the symlinks since it's the same directory
+            unset SCREEN_LOGDIR
+        fi
+    fi
+    unset default_logdir logfile
+fi
+
+# LOGDIR is always set at this point so it is not useful as a 'enable' for service logs
+# SCREEN_LOGDIR may be set, it is useful to enable the compat symlinks
+
 # Local variables:
 # mode: shell-script
 # End:
diff --git a/tests/test_functions.sh b/tests/test_functions.sh
new file mode 100755
index 0000000..e57948a
--- /dev/null
+++ b/tests/test_functions.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+# Tests for DevStack meta-config functions
+
+TOP=$(cd $(dirname "$0")/.. && pwd)
+
+# Import common functions
+source $TOP/functions
+source $TOP/tests/unittest.sh
+
+function test_truefalse {
+    local one=1
+    local captrue=True
+    local lowtrue=true
+    local abrevtrue=t
+    local zero=0
+    local capfalse=False
+    local lowfalse=false
+    local abrevfalse=f
+    for against in True False; do
+        for name in one captrue lowtrue abrevtrue; do
+            assert_equal "True" $(trueorfalse $against $name) "\$(trueorfalse $against $name)"
+        done
+    done
+    for against in True False; do
+        for name in zero capfalse lowfalse abrevfalse; do
+            assert_equal "False" $(trueorfalse $against $name) "\$(trueorfalse $against $name)"
+        done
+    done
+}
+
+test_truefalse
+
+report_results
diff --git a/tests/unittest.sh b/tests/unittest.sh
new file mode 100644
index 0000000..435cc3a
--- /dev/null
+++ b/tests/unittest.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+# we always start with no errors
+ERROR=0
+FAILED_FUNCS=""
+
+function assert_equal {
+    local lineno=`caller 0 | awk '{print $1}'`
+    local function=`caller 0 | awk '{print $2}'`
+    local msg=$3
+    if [[ "$1" != "$2" ]]; then
+        FAILED_FUNCS+="$function:L$lineno\n"
+        echo "ERROR: $1 != $2 in $function:L$lineno!"
+        echo "  $msg"
+        ERROR=1
+    else
+        echo "$function:L$lineno - ok"
+    fi
+}
+
+function report_results {
+    if [[ $ERROR -eq 1 ]]; then
+        echo "Tests FAILED"
+        echo $FAILED_FUNCS
+        exit 1
+    fi
+}
diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh
index 26aae82..cc5275f 100755
--- a/tools/fixup_stuff.sh
+++ b/tools/fixup_stuff.sh
@@ -12,12 +12,10 @@
 # - httplib2 0.8 permissions are 600 in the package and
 #   pip 1.4 doesn't fix it (1.3 did)
 #
-# - RHEL6:
-#
+# - Fedora:
 #   - set selinux not enforcing
-#   - (re)start messagebus daemon
-#   - remove distro packages python-crypto and python-lxml
-#   - pre-install hgtools to work around a bug in RHEL6 distribute
+#   - uninstall firewalld (f20 only)
+
 
 # If TOP_DIR is set we're being sourced rather than running stand-alone
 # or in a sub-shell
@@ -111,8 +109,8 @@
     fi
 
     FORCE_FIREWALLD=$(trueorfalse False $FORCE_FIREWALLD)
-    if [[ ${DISTRO} =~ (f19|f20) && $FORCE_FIREWALLD == "False" ]]; then
-        # On Fedora 19 and 20 firewalld interacts badly with libvirt and
+    if [[ ${DISTRO} =~ (f20) && $FORCE_FIREWALLD == "False" ]]; then
+        # On Fedora 20 firewalld interacts badly with libvirt and
         # slows things down significantly.  However, for those cases
         # where that combination is desired, allow this fix to be skipped.
 
@@ -125,64 +123,3 @@
     fi
 
 fi
-
-# RHEL6
-# -----
-
-if [[ $DISTRO =~ (rhel6) ]]; then
-
-    # install_pip.sh installs the latest setuptools over the packaged
-    # version.  We can't really uninstall the packaged version if it
-    # is there, because it may remove other important things like
-    # cloud-init.  Things work, but there can be an old egg file left
-    # around from the package that causes some really strange
-    # setuptools errors.  Remove it, if it is there
-    sudo rm -f /usr/lib/python2.6/site-packages/setuptools-0.6*.egg-info
-
-    # If the ``dbus`` package was installed by DevStack dependencies the
-    # uuid may not be generated because the service was never started (PR#598200),
-    # causing Nova to stop later on complaining that ``/var/lib/dbus/machine-id``
-    # does not exist.
-    sudo service messagebus restart
-
-    # The following workarounds break xenserver
-    if [ "$VIRT_DRIVER" != 'xenserver' ]; then
-        # An old version of ``python-crypto`` (2.0.1) may be installed on a
-        # fresh system via Anaconda and the dependency chain
-        # ``cas`` -> ``python-paramiko`` -> ``python-crypto``.
-        # ``pip uninstall pycrypto`` will remove the packaged ``.egg-info``
-        # file but leave most of the actual library files behind in
-        # ``/usr/lib64/python2.6/Crypto``. Later ``pip install pycrypto``
-        # will install over the packaged files resulting
-        # in a useless mess of old, rpm-packaged files and pip-installed files.
-        # Remove the package so that ``pip install python-crypto`` installs
-        # cleanly.
-        # Note: other RPM packages may require ``python-crypto`` as well.
-        # For example, RHEL6 does not install ``python-paramiko packages``.
-        uninstall_package python-crypto
-
-        # A similar situation occurs with ``python-lxml``, which is required by
-        # ``ipa-client``, an auditing package we don't care about.  The
-        # build-dependencies needed for ``pip install lxml`` (``gcc``,
-        # ``libxml2-dev`` and ``libxslt-dev``) are present in
-        # ``files/rpms/general``.
-        uninstall_package python-lxml
-    fi
-
-    # ``setup.py`` contains a ``setup_requires`` package that is supposed
-    # to be transient.  However, RHEL6 distribute has a bug where
-    # ``setup_requires`` registers entry points that are not cleaned
-    # out properly after the setup-phase resulting in installation failures
-    # (bz#924038).  Pre-install the problem package so the ``setup_requires``
-    # dependency is satisfied and it will not be installed transiently.
-    # Note we do this before the track-depends in ``stack.sh``.
-    pip_install hgtools
-
-    # workaround for https://code.google.com/p/unittest-ext/issues/detail?id=79
-    install_package python-unittest2 patch
-    pip_install discover
-    (cd /usr/lib/python2.6/site-packages/; sudo patch <"$FILES/patches/unittest2-discover.patch" || echo 'Assume already applied')
-    # Make sure the discover.pyc is up to date
-    sudo rm /usr/lib/python2.6/site-packages/discover.pyc || true
-    sudo python -c 'import discover'
-fi
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index d57a687..73d0947 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -43,7 +43,7 @@
 
 function install_get_pip {
     if [[ ! -r $LOCAL_PIP ]]; then
-        curl -o $LOCAL_PIP $PIP_GET_PIP_URL || \
+        curl --retry 6 --retry-delay 5 -o $LOCAL_PIP $PIP_GET_PIP_URL || \
             die $LINENO "Download of get-pip.py failed"
     fi
     sudo -H -E python $LOCAL_PIP
diff --git a/tools/install_prereqs.sh b/tools/install_prereqs.sh
index 9651083..303cc63 100755
--- a/tools/install_prereqs.sh
+++ b/tools/install_prereqs.sh
@@ -8,9 +8,15 @@
 #
 # -f        Force an install run now
 
-if [[ -n "$1" &&  "$1" = "-f" ]]; then
-    FORCE_PREREQ=1
-fi
+FORCE_PREREQ=0
+
+while getopts ":f" opt; do
+    case $opt in
+        f)
+            FORCE_PREREQ=1
+            ;;
+    esac
+done
 
 # If TOP_DIR is set we're being sourced rather than running stand-alone
 # or in a sub-shell
diff --git a/tools/xen/build_xva.sh b/tools/xen/build_xva.sh
index 7c8e620..7002e6e 100755
--- a/tools/xen/build_xva.sh
+++ b/tools/xen/build_xva.sh
@@ -119,9 +119,7 @@
 
     chown -R $STACK_USER /opt/stack
 
-    if su -c "/opt/stack/run.sh" $STACK_USER; then
-        touch /var/run/devstack.succeeded
-    fi
+    su -c "/opt/stack/run.sh" $STACK_USER
 
     # Update /etc/issue
     {
@@ -177,8 +175,19 @@
 cat <<EOF >$STAGING_DIR/opt/stack/run.sh
 #!/bin/bash
 set -eux
-cd /opt/stack/devstack
-./unstack.sh || true
-./stack.sh
+(
+  flock -n 9 || exit 1
+
+  [ -e /opt/stack/runsh.succeeded ] && rm /opt/stack/runsh.succeeded
+  echo \$\$ >> /opt/stack/run_sh.pid
+
+  cd /opt/stack/devstack
+  ./unstack.sh || true
+  ./stack.sh
+
+  # Got to the end - success
+  touch /opt/stack/runsh.succeeded
+  rm /opt/stack/run_sh.pid
+) 9> /opt/stack/.runsh_lock
 EOF
 chmod 755 $STAGING_DIR/opt/stack/run.sh
diff --git a/tools/xen/install_os_domU.sh b/tools/xen/install_os_domU.sh
index 3a63473..546ead6 100755
--- a/tools/xen/install_os_domU.sh
+++ b/tools/xen/install_os_domU.sh
@@ -365,25 +365,27 @@
 if [ "$WAIT_TILL_LAUNCH" = "1" ]  && [ -e ~/.ssh/id_rsa.pub  ] && [ "$COPYENV" = "1" ]; then
     set +x
 
-    echo "VM Launched - Waiting for devstack to start"
-    while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "service devstack status | grep -q running"; do
+    echo "VM Launched - Waiting for run.sh"
+    while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "test -e /opt/stack/run_sh.pid"; do
         sleep 10
     done
     echo -n "devstack service is running, waiting for stack.sh to start logging..."
 
-    while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "test -e /tmp/devstack/log/stack.log"; do
-        sleep 10
-    done
+    pid=`ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "cat /opt/stack/run_sh.pid"`
+    if [ -n "$SCREEN_LOGDIR" ]; then
+        while ! ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "test -e ${SCREEN_LOGDIR}/stack.log"; do
+            sleep 10
+        done
+
+        ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "tail --pid $pid -n +1 -f ${SCREEN_LOGDIR}/stack.log"
+    else
+        echo -n "SCREEN_LOGDIR not set; just waiting for process $pid to finish"
+        ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "wait $pid"
+    fi
+
     set -x
-
-    # Watch devstack's output (which doesn't start until stack.sh is running,
-    # but wait for run.sh (which starts stack.sh) to exit as that is what
-    # hopefully writes the succeeded cookie.
-    pid=`ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS pgrep run.sh`
-    ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS "tail --pid $pid -n +1 -f /tmp/devstack/log/stack.log"
-
     # Fail if devstack did not succeed
-    ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS 'test -e /var/run/devstack.succeeded'
+    ssh_no_check -q stack@$OS_VM_MANAGEMENT_ADDRESS 'test -e /opt/stack/runsh.succeeded'
 
     set +x
     echo "################################################################################"
@@ -401,7 +403,7 @@
     echo ""
     echo "ssh into your domU now: 'ssh stack@$OS_VM_MANAGEMENT_ADDRESS' using your password"
     echo "and then do: 'sudo service devstack status' to check if devstack is still running."
-    echo "Check that /var/run/devstack.succeeded exists"
+    echo "Check that /opt/stack/runsh.succeeded exists"
     echo ""
     echo "When devstack completes, you can visit the OpenStack Dashboard"
     echo "at http://$OS_VM_SERVICES_ADDRESS, and contact other services at the usual ports."
diff --git a/unstack.sh b/unstack.sh
index ea45da9..b8b7f4a 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -6,11 +6,22 @@
 # mysql and rabbit are left running as OpenStack code refreshes
 # do not require them to be restarted.
 #
-# Stop all processes by setting ``UNSTACK_ALL`` or specifying ``--all``
+# Stop all processes by setting ``UNSTACK_ALL`` or specifying ``-a``
 # on the command line
 
+UNSTACK_ALL=""
+
+while getopts ":a" opt; do
+    case $opt in
+        a)
+            UNSTACK_ALL=""
+            ;;
+    esac
+done
+
 # Keep track of the current devstack directory.
 TOP_DIR=$(cd $(dirname "$0") && pwd)
+FILES=$TOP_DIR/files
 
 # Import common functions
 source $TOP_DIR/functions
@@ -19,7 +30,7 @@
 source $TOP_DIR/lib/database
 
 # Load local configuration
-source $TOP_DIR/stackrc
+source $TOP_DIR/openrc
 
 # Destination path for service data
 DATA_DIR=${DATA_DIR:-${DEST}/data}
@@ -44,6 +55,7 @@
 source $TOP_DIR/lib/infra
 source $TOP_DIR/lib/oslo
 source $TOP_DIR/lib/stackforge
+source $TOP_DIR/lib/lvm
 source $TOP_DIR/lib/horizon
 source $TOP_DIR/lib/keystone
 source $TOP_DIR/lib/glance
@@ -72,10 +84,6 @@
 # ``os_RELEASE``, ``os_UPDATE``, ``os_PACKAGE``, ``os_CODENAME``
 GetOSVersion
 
-if [[ "$1" == "--all" ]]; then
-    UNSTACK_ALL=${UNSTACK_ALL:-1}
-fi
-
 # Run extras
 # ==========
 
@@ -170,3 +178,5 @@
         screen -X -S $SESSION quit
     fi
 fi
+
+clean_lvm_volume_group $DEFAULT_VOLUME_GROUP_NAME