Merge "One last format and content cleanup for the index page"
diff --git a/exercises/trove.sh b/exercises/trove.sh
deleted file mode 100755
index 053f872..0000000
--- a/exercises/trove.sh
+++ /dev/null
@@ -1,49 +0,0 @@
-#!/usr/bin/env bash
-
-# **trove.sh**
-
-# Sanity check that trove started if enabled
-
-echo "*********************************************************************"
-echo "Begin DevStack Exercise: $0"
-echo "*********************************************************************"
-
-# This script exits on an error so that errors don't compound and you see
-# only the first error that occurred.
-set -o errexit
-
-# Print the commands being run so that we can see the command that triggers
-# an error.  It is also useful for following allowing as the install occurs.
-set -o xtrace
-
-
-# Settings
-# ========
-
-# Keep track of the current directory
-EXERCISE_DIR=$(cd $(dirname "$0") && pwd)
-TOP_DIR=$(cd $EXERCISE_DIR/..; pwd)
-
-# Import common functions
-source $TOP_DIR/functions
-
-# Import configuration
-source $TOP_DIR/openrc
-
-# Import exercise configuration
-source $TOP_DIR/exerciserc
-
-is_service_enabled trove || exit 55
-
-# can try to get datastore id
-DSTORE_ID=$(trove datastore-list | tail -n +4 |head -3 | get_field 1)
-die_if_not_set $LINENO  DSTORE_ID "Trove API not functioning!"
-
-DV_ID=$(trove datastore-version-list $DSTORE_ID | tail -n +4 | get_field 1)
-die_if_not_set $LINENO DV_ID "Trove API not functioning!"
-
-set +o xtrace
-echo "*********************************************************************"
-echo "SUCCESS: End DevStack Exercise: $0"
-echo "*********************************************************************"
-
diff --git a/extras.d/70-trove.sh b/extras.d/70-trove.sh
index a4dc7fb..f284354 100644
--- a/extras.d/70-trove.sh
+++ b/extras.d/70-trove.sh
@@ -11,7 +11,6 @@
         cleanup_trove
     elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
         echo_summary "Configuring Trove"
-        configure_troveclient
         configure_trove
 
         if is_service_enabled key; then
diff --git a/files/rpms-suse/general b/files/rpms-suse/general
index 0a4746f..f1f7e8f 100644
--- a/files/rpms-suse/general
+++ b/files/rpms-suse/general
@@ -22,3 +22,4 @@
 tcpdump
 unzip
 wget
+net-tools
diff --git a/files/rpms/cinder b/files/rpms/cinder
index ce6181e..eedff18 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,rhel7
+python-lxml         #dist:f19,f20,f21,rhel7
diff --git a/files/rpms/general b/files/rpms/general
index d4a9fcb..d7ace9b 100644
--- a/files/rpms/general
+++ b/files/rpms/general
@@ -27,6 +27,7 @@
 bc
 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)
diff --git a/files/rpms/glance b/files/rpms/glance
index 5a7f073..d2792cf 100644
--- a/files/rpms/glance
+++ b/files/rpms/glance
@@ -6,10 +6,10 @@
 python-argparse
 python-eventlet
 python-greenlet
-python-lxml         #dist:f19,f20,rhel7
-python-paste-deploy #dist:f19,f20,rhel7
+python-lxml         #dist:f19,f20,f21,rhel7
+python-paste-deploy #dist:f19,f20,f21,rhel7
 python-routes
 python-sqlalchemy
-python-wsgiref      #dist:f18,f19,f20
+python-wsgiref      #dist:f18,f19,f20,f21
 pyxattr
 zlib-devel          # testonly
diff --git a/files/rpms/horizon b/files/rpms/horizon
index 7add23a..1d06ac2 100644
--- a/files/rpms/horizon
+++ b/files/rpms/horizon
@@ -12,8 +12,8 @@
 python-migrate
 python-mox
 python-nose
-python-paste        #dist:f19,f20
-python-paste-deploy #dist:f19,f20
+python-paste        #dist:f19,f20,f21
+python-paste-deploy #dist:f19,f20,f21
 python-routes
 python-sphinx
 python-sqlalchemy
diff --git a/files/rpms/keystone b/files/rpms/keystone
index ce41ee5..8b0953d 100644
--- a/files/rpms/keystone
+++ b/files/rpms/keystone
@@ -1,10 +1,10 @@
 MySQL-python
 python-greenlet
-libxslt-devel       # dist:f20
-python-lxml         #dist:f19,f20
-python-paste        #dist:f19,f20
-python-paste-deploy #dist:f19,f20
-python-paste-script #dist:f19,f20
+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
 python-routes
 python-sqlalchemy
 python-webob
diff --git a/files/rpms/neutron b/files/rpms/neutron
index 2c9dd3d..f2473fb 100644
--- a/files/rpms/neutron
+++ b/files/rpms/neutron
@@ -12,8 +12,8 @@
 python-greenlet
 python-iso8601
 #rhel6 gets via pip
-python-paste        # dist:f19,f20,rhel7
-python-paste-deploy # dist:f19,f20,rhel7
+python-paste        # dist:f19,f20,f21,rhel7
+python-paste-deploy # dist:f19,f20,f21,rhel7
 python-qpid # NOPRIME
 python-routes
 python-sqlalchemy
diff --git a/files/rpms/nova b/files/rpms/nova
index f3261c6..07f13c7 100644
--- a/files/rpms/nova
+++ b/files/rpms/nova
@@ -29,11 +29,11 @@
 python-lockfile
 python-migrate
 python-mox
-python-paramiko # dist:f19,f20,rhel7
+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,rhel7
-python-paste-deploy # dist:f19,f20,rhel7
+python-paste        # dist:f19,f20,f21,rhel7
+python-paste-deploy # dist:f19,f20,f21,rhel7
 python-qpid # NOPRIME
 python-routes
 python-sqlalchemy
diff --git a/files/rpms/swift b/files/rpms/swift
index 9ec4aab..ccda22b 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,rhel7
+python-paste-deploy # dist:f19,f20,f21,rhel7
 python-simplejson
 python-webob
 pyxattr
diff --git a/functions-common b/functions-common
index 9f8476e..e890b75 100644
--- a/functions-common
+++ b/functions-common
@@ -25,7 +25,6 @@
 # - ``FILES``
 # - ``OFFLINE``
 # - ``PIP_DOWNLOAD_CACHE``
-# - ``PIP_USE_MIRRORS``
 # - ``RECLONE``
 # - ``REQUIREMENTS_DIR``
 # - ``STACK_USER``
@@ -1559,7 +1558,7 @@
 }
 
 # Wrapper for ``pip install`` to set cache and proxy environment variables
-# Uses globals ``OFFLINE``, ``PIP_DOWNLOAD_CACHE``, ``PIP_USE_MIRRORS``,
+# Uses globals ``OFFLINE``, ``PIP_DOWNLOAD_CACHE``,
 # ``TRACK_DEPENDS``, ``*_proxy``
 # pip_install package [package ...]
 function pip_install {
@@ -1585,21 +1584,13 @@
         local sudo_pip="sudo"
     fi
 
-    # Mirror option not needed anymore because pypi has CDN available,
-    # but it's useful in certain circumstances
-    PIP_USE_MIRRORS=${PIP_USE_MIRRORS:-False}
-    local pip_mirror_opt=""
-    if [[ "$PIP_USE_MIRRORS" != "False" ]]; then
-        pip_mirror_opt="--use-mirrors"
-    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 \
         $cmd_pip install \
-        $pip_mirror_opt $@
+        $@
 
     INSTALL_TESTONLY_PACKAGES=$(trueorfalse False $INSTALL_TESTONLY_PACKAGES)
     if [[ "$INSTALL_TESTONLY_PACKAGES" == "True" ]]; then
@@ -1610,7 +1601,7 @@
                 https_proxy=$https_proxy \
                 no_proxy=$no_proxy \
                 $cmd_pip install \
-                $pip_mirror_opt -r $test_req
+                -r $test_req
         fi
     fi
 }
@@ -1634,6 +1625,17 @@
     setup_install $dir
 }
 
+# setup a library by name in editiable mode. If we are trying to use
+# the library from git, we'll do a git based install, otherwise we'll
+# punt and the library should be installed by a requirements pull from
+# another project.
+#
+# use this for non namespaced libraries
+function setup_dev_lib {
+    local name=$1
+    local dir=${GITDIR[$name]}
+    setup_develop $dir
+}
 
 # this should be used if you want to install globally, all libraries should
 # use this, especially *oslo* ones
diff --git a/lib/ceilometer b/lib/ceilometer
index 483cd27..c4377e0 100644
--- a/lib/ceilometer
+++ b/lib/ceilometer
@@ -35,8 +35,9 @@
 # --------
 
 # Set up default directories
+GITDIR["python-ceilometerclient"]=$DEST/python-ceilometerclient
+
 CEILOMETER_DIR=$DEST/ceilometer
-CEILOMETERCLIENT_DIR=$DEST/python-ceilometerclient
 CEILOMETER_CONF_DIR=/etc/ceilometer
 CEILOMETER_CONF=$CEILOMETER_CONF_DIR/ceilometer.conf
 CEILOMETER_API_LOG_DIR=/var/log/ceilometer-api
@@ -268,9 +269,11 @@
 
 # install_ceilometerclient() - Collect source and prepare
 function install_ceilometerclient {
-    git_clone $CEILOMETERCLIENT_REPO $CEILOMETERCLIENT_DIR $CEILOMETERCLIENT_BRANCH
-    setup_develop $CEILOMETERCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$CEILOMETERCLIENT_DIR/tools/,/etc/bash_completion.d/}ceilometer.bash_completion
+    if use_library_from_git "python-ceilometerclient"; then
+        git_clone_by_name "python-ceilometerclient"
+        setup_dev_lib "python-ceilometerclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ceilometerclient"]}/tools/,/etc/bash_completion.d/}ceilometer.bash_completion
+    fi
 }
 
 # start_ceilometer() - Start running processes, including screen
diff --git a/lib/ceph b/lib/ceph
index e55738c..2ddf5db 100644
--- a/lib/ceph
+++ b/lib/ceph
@@ -71,6 +71,11 @@
 # Functions
 # ------------
 
+function get_ceph_version {
+    local ceph_version_str=$(sudo ceph daemon mon.$(hostname) version | cut -d '"' -f 4)
+    echo $ceph_version_str
+}
+
 # import_libvirt_secret_ceph() - Imports Cinder user key into libvirt
 # so it can connect to the Ceph cluster while attaching a Cinder block device
 function import_libvirt_secret_ceph {
@@ -154,10 +159,16 @@
         sleep 5
     done
 
+    # pools data and metadata were removed in the Giant release so depending on the version we apply different commands
+    local ceph_version=$(get_ceph_version)
     # change pool replica size according to the CEPH_REPLICAS set by the user
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set data size ${CEPH_REPLICAS}
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd size ${CEPH_REPLICAS}
-    sudo ceph -c ${CEPH_CONF_FILE} osd pool set metadata size ${CEPH_REPLICAS}
+    if [[ ${ceph_version%.*} -eq 0 ]] && [[ ${ceph_version##*.} -lt 87 ]]; then
+        sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd size ${CEPH_REPLICAS}
+        sudo ceph -c ${CEPH_CONF_FILE} osd pool set data size ${CEPH_REPLICAS}
+        sudo ceph -c ${CEPH_CONF_FILE} osd pool set metadata size ${CEPH_REPLICAS}
+    else
+        sudo ceph -c ${CEPH_CONF_FILE} osd pool set rbd size ${CEPH_REPLICAS}
+    fi
 
     # create a simple rule to take OSDs instead of host with CRUSH
     # then apply this rules to the default pool
diff --git a/lib/cinder b/lib/cinder
index 29cda42..eb3cbe8 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -36,8 +36,9 @@
 fi
 
 # set up default directories
+GITDIR["python-cinderclient"]=$DEST/python-cinderclient
+
 CINDER_DIR=$DEST/cinder
-CINDERCLIENT_DIR=$DEST/python-cinderclient
 CINDER_STATE_PATH=${CINDER_STATE_PATH:=$DATA_DIR/cinder}
 CINDER_AUTH_CACHE_DIR=${CINDER_AUTH_CACHE_DIR:-/var/cache/cinder}
 
@@ -402,9 +403,11 @@
 
 # install_cinderclient() - Collect source and prepare
 function install_cinderclient {
-    git_clone $CINDERCLIENT_REPO $CINDERCLIENT_DIR $CINDERCLIENT_BRANCH
-    setup_develop $CINDERCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion
+    if use_library_from_git "python-cinderclient"; then
+        git_clone_by_name "python-cinderclient"
+        setup_dev_lib "python-cinderclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-cinderclient"]}/tools/,/etc/bash_completion.d/}cinder.bash_completion
+    fi
 }
 
 # apply config.d approach for cinder volumes directory
diff --git a/lib/databases/mysql b/lib/databases/mysql
index 67bf85a..7a444a3 100644
--- a/lib/databases/mysql
+++ b/lib/databases/mysql
@@ -26,10 +26,10 @@
         sudo rm -rf /etc/mysql
         return
     elif is_fedora; then
-        if [[ $DISTRO =~ (rhel7) ]]; then
-            MYSQL=mariadb
-        else
+        if [[ $DISTRO =~ (rhel6) ]]; then
             MYSQL=mysqld
+        else
+            MYSQL=mariadb
         fi
     elif is_suse; then
         MYSQL=mysql
@@ -54,10 +54,10 @@
         my_conf=/etc/mysql/my.cnf
         mysql=mysql
     elif is_fedora; then
-        if [[ $DISTRO =~ (rhel7) ]]; then
-            mysql=mariadb
-        else
+        if [[ $DISTRO =~ (rhel6) ]]; then
             mysql=mysqld
+        else
+            mysql=mariadb
         fi
         my_conf=/etc/my.cnf
     elif is_suse; then
@@ -142,10 +142,10 @@
     fi
     # Install mysql-server
     if is_ubuntu || is_fedora; then
-        if [[ $DISTRO =~ (rhel7) ]]; then
-            install_package mariadb-server
-        else
+        if [[ $DISTRO =~ (rhel6) ]]; then
             install_package mysql-server
+        else
+            install_package mariadb-server
         fi
     elif is_suse; then
         if ! is_package_installed mariadb; then
diff --git a/lib/glance b/lib/glance
index 4194842..04c088a 100644
--- a/lib/glance
+++ b/lib/glance
@@ -27,9 +27,10 @@
 # --------
 
 # Set up default directories
+GITDIR["python-glanceclient"]=$DEST/python-glanceclient
+GIRDIR["glance_store"]=$DEST/glance_store
+
 GLANCE_DIR=$DEST/glance
-GLANCE_STORE_DIR=$DEST/glance_store
-GLANCECLIENT_DIR=$DEST/python-glanceclient
 GLANCE_CACHE_DIR=${GLANCE_CACHE_DIR:=$DATA_DIR/glance/cache}
 GLANCE_IMAGE_DIR=${GLANCE_IMAGE_DIR:=$DATA_DIR/glance/images}
 GLANCE_AUTH_CACHE_DIR=${GLANCE_AUTH_CACHE_DIR:-/var/cache/glance}
@@ -286,16 +287,20 @@
 
 # install_glanceclient() - Collect source and prepare
 function install_glanceclient {
-    git_clone $GLANCECLIENT_REPO $GLANCECLIENT_DIR $GLANCECLIENT_BRANCH
-    setup_develop $GLANCECLIENT_DIR
+    if use_library_from_git "python-glanceclient"; then
+        git_clone_by_name "python-glanceclient"
+        setup_dev_lib "python-glanceclient"
+    fi
 }
 
 # install_glance() - Collect source and prepare
 function install_glance {
     # Install glance_store from git so we make sure we're testing
     # the latest code.
-    git_clone $GLANCE_STORE_REPO $GLANCE_STORE_DIR $GLANCE_STORE_BRANCH
-    setup_develop $GLANCE_STORE_DIR
+    if use_library_from_git "glance_store"; then
+        git_clone_by_name "glance_store"
+        setup_dev_lib "glance_store"
+    fi
 
     git_clone $GLANCE_REPO $GLANCE_DIR $GLANCE_BRANCH
     setup_develop $GLANCE_DIR
diff --git a/lib/heat b/lib/heat
index 53eca25..2b55cf0 100644
--- a/lib/heat
+++ b/lib/heat
@@ -29,8 +29,9 @@
 # --------
 
 # set up default directories
+GITDIR["python-heatclient"]=$DEST/python-heatclient
+
 HEAT_DIR=$DEST/heat
-HEATCLIENT_DIR=$DEST/python-heatclient
 HEAT_CFNTOOLS_DIR=$DEST/heat-cfntools
 HEAT_TEMPLATES_REPO_DIR=$DEST/heat-templates
 HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat}
@@ -183,9 +184,11 @@
 
 # install_heatclient() - Collect source and prepare
 function install_heatclient {
-    git_clone $HEATCLIENT_REPO $HEATCLIENT_DIR $HEATCLIENT_BRANCH
-    setup_develop $HEATCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$HEATCLIENT_DIR/tools/,/etc/bash_completion.d/}heat.bash_completion
+    if use_library_from_git "python-heatclient"; then
+        git_clone_by_name "python-heatclient"
+        setup_dev_lib "python-heatclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-heatclient"]}/tools/,/etc/bash_completion.d/}heat.bash_completion
+    fi
 }
 
 # install_heat() - Collect source and prepare
diff --git a/lib/horizon b/lib/horizon
index 0213948..1b53831 100644
--- a/lib/horizon
+++ b/lib/horizon
@@ -25,8 +25,9 @@
 # --------
 
 # Set up default directories
+GITDIR["django_openstack_auth"]=$DEST/django_openstack_auth
+
 HORIZON_DIR=$DEST/horizon
-HORIZONAUTH_DIR=$DEST/django_openstack_auth
 
 # local_settings.py is used to customize Dashboard settings.
 # The example file in Horizon repo is used by default.
@@ -89,9 +90,7 @@
     # Horizon is installed as develop mode, so we can compile here.
     # Message catalog compilation is handled by Django admin script,
     # so compiling them after the installation avoids Django installation twice.
-    cd $HORIZON_DIR
-    ./run_tests.sh -N --compilemessages
-    cd -
+    (cd $HORIZON_DIR; ./run_tests.sh -N --compilemessages)
 }
 
 # init_horizon() - Initialize databases, etc.
@@ -145,15 +144,16 @@
 
 # install_django_openstack_auth() - Collect source and prepare
 function install_django_openstack_auth {
-    git_clone $HORIZONAUTH_REPO $HORIZONAUTH_DIR $HORIZONAUTH_BRANCH
-
-    # Compile message catalogs before installation
-    _prepare_message_catalog_compilation
-    cd $HORIZONAUTH_DIR
-    python setup.py compile_catalog
-    cd -
-
-    setup_install $HORIZONAUTH_DIR
+    if use_library_from_git "django_openstack_auth"; then
+        local dir=${GITDIR["django_openstack_auth"]}
+        git_clone_by_name "django_openstack_auth"
+        # Compile message catalogs before installation
+        _prepare_message_catalog_compilation
+        (cd $dir; python setup.py compile_catalog)
+        setup_dev_lib "django_openstack_auth"
+    fi
+    # if we aren't using this library from git, then we just let it
+    # get dragged in by the horizon setup.
 }
 
 # install_horizon() - Collect source and prepare
diff --git a/lib/ironic b/lib/ironic
index cf005a7..afe69f2 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -28,11 +28,12 @@
 # --------
 
 # Set up default directories
+GITDIR["python-ironicclient"]=$DEST/python-ironicclient
+
 IRONIC_DIR=$DEST/ironic
 IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent
 IRONIC_DATA_DIR=$DATA_DIR/ironic
 IRONIC_STATE_PATH=/var/lib/ironic
-IRONICCLIENT_DIR=$DEST/python-ironicclient
 IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic}
 IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic}
 IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf
@@ -150,9 +151,14 @@
 
 # install_ironicclient() - Collect sources and prepare
 function install_ironicclient {
-    git_clone $IRONICCLIENT_REPO $IRONICCLIENT_DIR $IRONICCLIENT_BRANCH
-    setup_develop $IRONICCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$IRONICCLIENT_DIR/tools/,/etc/bash_completion.d/}ironic.bash_completion
+    if use_library_from_git "python-ironicclient"; then
+        git_clone_by_name "python-ironicclient"
+        setup_dev_lib "python-ironicclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-ironicclient"]}/tools/,/etc/bash_completion.d/}ironic.bash_completion
+    else
+        # nothing actually "requires" ironicclient, so force instally from pypi
+        pip_install python-ironicclient
+    fi
 }
 
 # _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file
diff --git a/lib/keystone b/lib/keystone
index 276e971..72a79be 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -33,6 +33,9 @@
 # --------
 
 # Set up default directories
+GITDIR["python-keystoneclient"]=$DEST/python-keystoneclient
+GITDIR["keystonemiddleware"]=$DEST/keystonemiddleware
+
 KEYSTONE_DIR=$DEST/keystone
 KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/keystone}
 KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf
@@ -44,9 +47,6 @@
     KEYSTONE_WSGI_DIR=${KEYSTONE_WSGI_DIR:-/var/www/keystone}
 fi
 
-KEYSTONEMIDDLEWARE_DIR=$DEST/keystonemiddleware
-KEYSTONECLIENT_DIR=$DEST/python-keystoneclient
-
 # Set up additional extensions, such as oauth1, federation
 # Example of KEYSTONE_EXTENSIONS=oauth1,federation
 KEYSTONE_EXTENSIONS=${KEYSTONE_EXTENSIONS:-}
@@ -479,15 +479,19 @@
 
 # install_keystoneclient() - Collect source and prepare
 function install_keystoneclient {
-    git_clone $KEYSTONECLIENT_REPO $KEYSTONECLIENT_DIR $KEYSTONECLIENT_BRANCH
-    setup_develop $KEYSTONECLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion
+    if use_library_from_git "python-keystoneclient"; then
+        git_clone_by_name "python-keystoneclient"
+        setup_dev_lib "python-keystoneclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-keystoneclient"]}/tools/,/etc/bash_completion.d/}keystone.bash_completion
+    fi
 }
 
 # install_keystonemiddleware() - Collect source and prepare
 function install_keystonemiddleware {
-    git_clone $KEYSTONEMIDDLEWARE_REPO $KEYSTONEMIDDLEWARE_DIR $KEYSTONEMIDDLEWARE_BRANCH
-    setup_install $KEYSTONEMIDDLEWARE_DIR
+    if use_library_from_git "keystonemiddleware"; then
+        git_clone_by_name "keystonemiddleware"
+        setup_dev_lib "keystonemiddleware"
+    fi
 }
 
 # install_keystone() - Collect source and prepare
diff --git a/lib/neutron b/lib/neutron
index eb07f40..8295a73 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -67,8 +67,10 @@
 
 
 # Set up default directories
+GITDIR["python-neutronclient"]=$DEST/python-neutronclient
+
+
 NEUTRON_DIR=$DEST/neutron
-NEUTRONCLIENT_DIR=$DEST/python-neutronclient
 NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron}
 
 # Support entry points installation of console scripts
@@ -131,6 +133,8 @@
 Q_NOTIFY_NOVA_PORT_DATA_CHANGES=${Q_NOTIFY_NOVA_PORT_DATA_CHANGES:-True}
 VIF_PLUGGING_IS_FATAL=${VIF_PLUGGING_IS_FATAL:-True}
 VIF_PLUGGING_TIMEOUT=${VIF_PLUGGING_TIMEOUT:-300}
+# Specify if the initial private and external networks should be created
+NEUTRON_CREATE_INITIAL_NETWORKS=${NEUTRON_CREATE_INITIAL_NETWORKS:-True}
 
 ## Provider Network Information
 PROVIDER_SUBNET_NAME=${PROVIDER_SUBNET_NAME:-"provider_net"}
@@ -616,9 +620,11 @@
 
 # install_neutronclient() - Collect source and prepare
 function install_neutronclient {
-    git_clone $NEUTRONCLIENT_REPO $NEUTRONCLIENT_DIR $NEUTRONCLIENT_BRANCH
-    setup_develop $NEUTRONCLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion
+    if use_library_from_git "python-neutronclient"; then
+        git_clone_by_name "python-neutronclient"
+        setup_dev_lib "python-neutronclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-neutronclient"]}/tools/,/etc/bash_completion.d/}neutron.bash_completion
+    fi
 }
 
 # install_neutron_agent_packages() - Collect source and prepare
diff --git a/lib/neutron_plugins/ml2 b/lib/neutron_plugins/ml2
index 44b947f..f9a9774 100644
--- a/lib/neutron_plugins/ml2
+++ b/lib/neutron_plugins/ml2
@@ -84,6 +84,11 @@
         fi
     fi
 
+
+    # Allow for setup the flat type network
+    if [[ -z "$Q_ML2_PLUGIN_FLAT_TYPE_OPTIONS" && -n "$PHYSICAL_NETWORK" ]]; then
+            Q_ML2_PLUGIN_FLAT_TYPE_OPTIONS="flat_networks=$Q_ML2_FLAT_PHYSNET_OPTIONS"
+    fi
     # REVISIT(rkukura): Setting firewall_driver here for
     # neutron.agent.securitygroups_rpc.is_firewall_enabled() which is
     # used in the server, in case no L2 agent is configured on the
@@ -110,6 +115,8 @@
 
     populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_vxlan $Q_ML2_PLUGIN_VXLAN_TYPE_OPTIONS
 
+    populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_flat $Q_ML2_PLUGIN_FLAT_TYPE_OPTIONS
+
     populate_ml2_config /$Q_PLUGIN_CONF_FILE ml2_type_vlan $Q_ML2_PLUGIN_VLAN_TYPE_OPTIONS
 
     if [[ "$Q_DVR_MODE" != "legacy" ]]; then
diff --git a/lib/neutron_plugins/nuage b/lib/neutron_plugins/nuage
index 52d85a2..70de8fa 100644
--- a/lib/neutron_plugins/nuage
+++ b/lib/neutron_plugins/nuage
@@ -7,7 +7,7 @@
 
 function neutron_plugin_create_nova_conf {
     NOVA_OVS_BRIDGE=${NOVA_OVS_BRIDGE:-"br-int"}
-    iniset $NOVA_CONF DEFAULT neutron_ovs_bridge $NOVA_OVS_BRIDGE
+    iniset $NOVA_CONF neutron ovs_bridge $NOVA_OVS_BRIDGE
     NOVA_VIF_DRIVER=${NOVA_VIF_DRIVER:-"nova.virt.libvirt.vif.LibvirtGenericVIFDriver"}
     LIBVIRT_FIREWALL_DRIVER=nova.virt.firewall.NoopFirewallDriver
     iniset $NOVA_CONF DEFAULT firewall_driver $LIBVIRT_FIREWALL_DRIVER
diff --git a/lib/nova b/lib/nova
index 0f83807..78906f7 100644
--- a/lib/nova
+++ b/lib/nova
@@ -29,8 +29,10 @@
 # --------
 
 # Set up default directories
+GITDIR["python-novaclient"]=$DEST/python-novaclient
+
+
 NOVA_DIR=$DEST/nova
-NOVACLIENT_DIR=$DEST/python-novaclient
 NOVA_STATE_PATH=${NOVA_STATE_PATH:=$DATA_DIR/nova}
 # INSTANCES_PATH is the previous name for this
 NOVA_INSTANCES_PATH=${NOVA_INSTANCES_PATH:=${INSTANCES_PATH:=$NOVA_STATE_PATH/instances}}
@@ -637,9 +639,11 @@
 
 # install_novaclient() - Collect source and prepare
 function install_novaclient {
-    git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH
-    setup_develop $NOVACLIENT_DIR
-    sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion
+    if use_library_from_git "python-novaclient"; then
+        git_clone_by_name "python-novaclient"
+        setup_dev_lib "python-novaclient"
+        sudo install -D -m 0644 -o $STACK_USER {${GITDIR["python-novaclient"]}/tools/,/etc/bash_completion.d/}nova.bash_completion
+    fi
 }
 
 # install_nova() - Collect source and prepare
diff --git a/lib/sahara b/lib/sahara
index 6d1bef5..4f1ba22 100644
--- a/lib/sahara
+++ b/lib/sahara
@@ -22,15 +22,10 @@
 # --------
 
 # Set up default repos
-SAHARA_REPO=${SAHARA_REPO:-${GIT_BASE}/openstack/sahara.git}
-SAHARA_BRANCH=${SAHARA_BRANCH:-master}
-
-SAHARA_PYTHONCLIENT_REPO=${SAHARA_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-saharaclient.git}
-SAHARA_PYTHONCLIENT_BRANCH=${SAHARA_PYTHONCLIENT_BRANCH:-master}
 
 # Set up default directories
+GITDIR["python-saharaclient"]=$DEST/python-saharaclient
 SAHARA_DIR=$DEST/sahara
-SAHARA_PYTHONCLIENT_DIR=$DEST/python-saharaclient
 
 SAHARA_CONF_DIR=${SAHARA_CONF_DIR:-/etc/sahara}
 SAHARA_CONF_FILE=${SAHARA_CONF_DIR}/sahara.conf
@@ -158,8 +153,10 @@
 
 # install_python_saharaclient() - Collect source and prepare
 function install_python_saharaclient {
-    git_clone $SAHARA_PYTHONCLIENT_REPO $SAHARA_PYTHONCLIENT_DIR $SAHARA_PYTHONCLIENT_BRANCH
-    setup_develop $SAHARA_PYTHONCLIENT_DIR
+    if use_library_from_git "python-saharaclient"; then
+        git_clone_by_name "python-saharaclient"
+        setup_dev_lib "python-saharaclient"
+    fi
 }
 
 # start_sahara() - Start running processes, including screen
diff --git a/lib/swift b/lib/swift
index 7ef4496..ae0874e 100644
--- a/lib/swift
+++ b/lib/swift
@@ -34,8 +34,10 @@
 fi
 
 # Set up default directories
+GITDIR["python-swiftclient"]=$DEST/python-swiftclient
+
+
 SWIFT_DIR=$DEST/swift
-SWIFTCLIENT_DIR=$DEST/python-swiftclient
 SWIFT_AUTH_CACHE_DIR=${SWIFT_AUTH_CACHE_DIR:-/var/cache/swift}
 SWIFT_APACHE_WSGI_DIR=${SWIFT_APACHE_WSGI_DIR:-/var/www/swift}
 SWIFT3_DIR=$DEST/swift3
@@ -675,8 +677,10 @@
 }
 
 function install_swiftclient {
-    git_clone $SWIFTCLIENT_REPO $SWIFTCLIENT_DIR $SWIFTCLIENT_BRANCH
-    setup_develop $SWIFTCLIENT_DIR
+    if use_library_from_git "python-swiftclient"; then
+        git_clone_by_name "python-swiftclient"
+        setup_dev_lib "python-swiftclient"
+    fi
 }
 
 # start_swift() - Start running processes, including screen
diff --git a/lib/tempest b/lib/tempest
index 66f1a78..9e025a1 100644
--- a/lib/tempest
+++ b/lib/tempest
@@ -45,11 +45,12 @@
 # --------
 
 # Set up default directories
+GITDIR["tempest_lib"]=$DEST/tempest-lib
+
 TEMPEST_DIR=$DEST/tempest
 TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc}
 TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf
 TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest}
-TEMPEST_LIB_DIR=$DEST/tempest-lib
 
 NOVA_SOURCE_DIR=$DEST/nova
 
@@ -110,34 +111,36 @@
     # ... Also ensure we only take active images, so we don't get snapshots in process
     declare -a images
 
-    while read -r IMAGE_NAME IMAGE_UUID; do
-        if [ "$IMAGE_NAME" = "$DEFAULT_IMAGE_NAME" ]; then
-            image_uuid="$IMAGE_UUID"
-            image_uuid_alt="$IMAGE_UUID"
-        fi
-        images+=($IMAGE_UUID)
-    # TODO(stevemar): update this command to use openstackclient's `openstack image list`
-    # when it supports listing by status.
-    done < <(glance image-list --status=active | awk -F'|' '!/^(+--)|ID|aki|ari/ { print $3,$2 }')
+    if is_service_enabled glance; then
+        while read -r IMAGE_NAME IMAGE_UUID; do
+            if [ "$IMAGE_NAME" = "$DEFAULT_IMAGE_NAME" ]; then
+                image_uuid="$IMAGE_UUID"
+                image_uuid_alt="$IMAGE_UUID"
+            fi
+            images+=($IMAGE_UUID)
+        # TODO(stevemar): update this command to use openstackclient's `openstack image list`
+        # when it supports listing by status.
+        done < <(glance image-list --status=active | awk -F'|' '!/^(+--)|ID|aki|ari/ { print $3,$2 }')
 
-    case "${#images[*]}" in
-        0)
-            echo "Found no valid images to use!"
-            exit 1
-            ;;
-        1)
-            if [ -z "$image_uuid" ]; then
-                image_uuid=${images[0]}
-                image_uuid_alt=${images[0]}
-            fi
-            ;;
-        *)
-            if [ -z "$image_uuid" ]; then
-                image_uuid=${images[0]}
-                image_uuid_alt=${images[1]}
-            fi
-            ;;
-    esac
+        case "${#images[*]}" in
+            0)
+                echo "Found no valid images to use!"
+                exit 1
+                ;;
+            1)
+                if [ -z "$image_uuid" ]; then
+                    image_uuid=${images[0]}
+                    image_uuid_alt=${images[0]}
+                fi
+                ;;
+            *)
+                if [ -z "$image_uuid" ]; then
+                    image_uuid=${images[0]}
+                    image_uuid_alt=${images[1]}
+                fi
+                ;;
+        esac
+    fi
 
     # Create tempest.conf from tempest.conf.sample
     # copy every time, because the image UUIDS are going to change
@@ -161,63 +164,65 @@
     ALT_TENANT_NAME=${ALT_TENANT_NAME:-alt_demo}
     ADMIN_TENANT_ID=$(openstack project list | awk "/ admin / { print \$2 }")
 
-    # If the ``DEFAULT_INSTANCE_TYPE`` not declared, use the new behavior
-    # Tempest creates instane types for himself
-    if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
-        available_flavors=$(nova flavor-list)
-        if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then
-            if is_arch "ppc64"; then
-                # qemu needs at least 128MB of memory to boot on ppc64
-                nova flavor-create m1.nano 42 128 0 1
-            else
-                nova flavor-create m1.nano 42 64 0 1
+    if is_service_enabled nova; then
+        # If the ``DEFAULT_INSTANCE_TYPE`` not declared, use the new behavior
+        # Tempest creates instane types for himself
+        if  [[ -z "$DEFAULT_INSTANCE_TYPE" ]]; then
+            available_flavors=$(nova flavor-list)
+            if [[ ! ( $available_flavors =~ 'm1.nano' ) ]]; then
+                if is_arch "ppc64"; then
+                    # qemu needs at least 128MB of memory to boot on ppc64
+                    nova flavor-create m1.nano 42 128 0 1
+                else
+                    nova flavor-create m1.nano 42 64 0 1
+                fi
             fi
-        fi
-        flavor_ref=42
-        boto_instance_type=m1.nano
-        if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then
-            if is_arch "ppc64"; then
-                nova flavor-create m1.micro 84 256 0 1
-            else
-                nova flavor-create m1.micro 84 128 0 1
+            flavor_ref=42
+            boto_instance_type=m1.nano
+            if [[ ! ( $available_flavors =~ 'm1.micro' ) ]]; then
+                if is_arch "ppc64"; then
+                    nova flavor-create m1.micro 84 256 0 1
+                else
+                    nova flavor-create m1.micro 84 128 0 1
+                fi
             fi
-        fi
-        flavor_ref_alt=84
-    else
-        # Check Nova for existing flavors and, if set, look for the
-        # ``DEFAULT_INSTANCE_TYPE`` and use that.
-        boto_instance_type=$DEFAULT_INSTANCE_TYPE
-        flavor_lines=`nova flavor-list`
-        IFS=$'\r\n'
-        flavors=""
-        for line in $flavor_lines; do
-            f=$(echo $line | awk "/ $DEFAULT_INSTANCE_TYPE / { print \$2 }")
-            flavors="$flavors $f"
-        done
+            flavor_ref_alt=84
+        else
+            # Check Nova for existing flavors and, if set, look for the
+            # ``DEFAULT_INSTANCE_TYPE`` and use that.
+            boto_instance_type=$DEFAULT_INSTANCE_TYPE
+            flavor_lines=`nova flavor-list`
+            IFS=$'\r\n'
+            flavors=""
+            for line in $flavor_lines; do
+                f=$(echo $line | awk "/ $DEFAULT_INSTANCE_TYPE / { print \$2 }")
+                flavors="$flavors $f"
+            done
 
-        for line in $flavor_lines; do
-            flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
-        done
+            for line in $flavor_lines; do
+                flavors="$flavors `echo $line | grep -v "^\(|\s*ID\|+--\)" | cut -d' ' -f2`"
+            done
 
-        IFS=" "
-        flavors=($flavors)
-        num_flavors=${#flavors[*]}
-        echo "Found $num_flavors flavors"
-        if [[ $num_flavors -eq 0 ]]; then
-            echo "Found no valid flavors to use!"
-            exit 1
-        fi
-        flavor_ref=${flavors[0]}
-        flavor_ref_alt=$flavor_ref
-
-        # ensure flavor_ref and flavor_ref_alt have different values
-        # some resize instance in tempest tests depends on this.
-        for f in ${flavors[@]:1}; do
-            if [[ $f -ne $flavor_ref ]]; then
-                flavor_ref_alt=$f
-                break
+            IFS=" "
+            flavors=($flavors)
+            num_flavors=${#flavors[*]}
+            echo "Found $num_flavors flavors"
+            if [[ $num_flavors -eq 0 ]]; then
+                echo "Found no valid flavors to use!"
+                exit 1
             fi
-        done
+            flavor_ref=${flavors[0]}
+            flavor_ref_alt=$flavor_ref
+
+            # ensure flavor_ref and flavor_ref_alt have different values
+            # some resize instance in tempest tests depends on this.
+            for f in ${flavors[@]:1}; do
+                if [[ $f -ne $flavor_ref ]]; then
+                    flavor_ref_alt=$f
+                    break
+                fi
+            done
+        fi
     fi
 
     if [ "$Q_USE_NAMESPACE" != "False" ]; then
@@ -441,8 +446,10 @@
 
 # install_tempest_lib() - Collect source, prepare, and install tempest-lib
 function install_tempest_lib {
-    git_clone $TEMPEST_LIB_REPO $TEMPEST_LIB_DIR $TEMPEST_LIB_BRANCH
-    setup_develop $TEMPEST_LIB_DIR
+    if use_library_from_git "tempest_lib"; then
+        git_clone_by_name "tempest_lib"
+        setup_develop "tempest_lib"
+    fi
 }
 
 # install_tempest() - Collect source and prepare
@@ -460,20 +467,22 @@
     local kernel="$image_dir/${base_image_name}-vmlinuz"
     local ramdisk="$image_dir/${base_image_name}-initrd"
     local disk_image="$image_dir/${base_image_name}-blank.img"
-    # if the cirros uec downloaded and the system is uec capable
-    if [ -f "$kernel" -a -f "$ramdisk" -a -f "$disk_image" -a  "$VIRT_DRIVER" != "openvz" \
-        -a \( "$LIBVIRT_TYPE" != "lxc" -o "$VIRT_DRIVER" != "libvirt" \) ]; then
-        echo "Prepare aki/ari/ami Images"
-        mkdir -p $BOTO_MATERIALS_PATH
-        ( #new namespace
-            # tenant:demo ; user: demo
-            source $TOP_DIR/accrc/demo/demo
-            euca-bundle-image -r ${CIRROS_ARCH} -i "$kernel" --kernel true -d "$BOTO_MATERIALS_PATH"
-            euca-bundle-image -r ${CIRROS_ARCH} -i "$ramdisk" --ramdisk true -d "$BOTO_MATERIALS_PATH"
-            euca-bundle-image -r ${CIRROS_ARCH} -i "$disk_image" -d "$BOTO_MATERIALS_PATH"
-        ) 2>&1 </dev/null | cat
-    else
-        echo "Boto materials are not prepared"
+    if is_service_enabled nova; then
+        # if the cirros uec downloaded and the system is uec capable
+        if [ -f "$kernel" -a -f "$ramdisk" -a -f "$disk_image" -a  "$VIRT_DRIVER" != "openvz" \
+            -a \( "$LIBVIRT_TYPE" != "lxc" -o "$VIRT_DRIVER" != "libvirt" \) ]; then
+            echo "Prepare aki/ari/ami Images"
+            mkdir -p $BOTO_MATERIALS_PATH
+            ( #new namespace
+                # tenant:demo ; user: demo
+                source $TOP_DIR/accrc/demo/demo
+                euca-bundle-image -r ${CIRROS_ARCH} -i "$kernel" --kernel true -d "$BOTO_MATERIALS_PATH"
+                euca-bundle-image -r ${CIRROS_ARCH} -i "$ramdisk" --ramdisk true -d "$BOTO_MATERIALS_PATH"
+                euca-bundle-image -r ${CIRROS_ARCH} -i "$disk_image" -d "$BOTO_MATERIALS_PATH"
+            ) 2>&1 </dev/null | cat
+        else
+            echo "Boto materials are not prepared"
+        fi
     fi
 }
 
diff --git a/lib/trove b/lib/trove
index 4ac7293..60b2bdb 100644
--- a/lib/trove
+++ b/lib/trove
@@ -28,8 +28,9 @@
 fi
 
 # Set up default configuration
+GITDIR["python-troveclient"]=$DEST/python-troveclient
+
 TROVE_DIR=$DEST/trove
-TROVECLIENT_DIR=$DEST/python-troveclient
 TROVE_CONF_DIR=/etc/trove
 TROVE_LOCAL_CONF_DIR=$TROVE_DIR/etc/trove
 TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove}
@@ -109,10 +110,6 @@
     rm -fr $TROVE_CONF_DIR/*
 }
 
-# configure_troveclient() - Set config files, create data dirs, etc
-function configure_troveclient {
-    setup_develop $TROVECLIENT_DIR
-}
 
 # configure_trove() - Set config files, create data dirs, etc
 function configure_trove {
@@ -184,7 +181,10 @@
 
 # install_troveclient() - Collect source and prepare
 function install_troveclient {
-    git_clone $TROVECLIENT_REPO $TROVECLIENT_DIR $TROVECLIENT_BRANCH
+    if use_library_from_git "python-troveclient"; then
+        git_clone_by_name "python-troveclient"
+        setup_dev_lib "python-troveclient"
+    fi
 }
 
 # install_trove() - Collect source and prepare
diff --git a/stack.sh b/stack.sh
index 38ecceb..7635f32 100755
--- a/stack.sh
+++ b/stack.sh
@@ -143,7 +143,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|rhel6|rhel7) ]]; then
+if [[ ! ${DISTRO} =~ (precise|trusty|7.0|wheezy|sid|testing|jessie|f19|f20|f21|rhel6|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"
@@ -584,7 +584,7 @@
 fi
 
 # Set the destination directories for other OpenStack projects
-OPENSTACKCLIENT_DIR=$DEST/python-openstackclient
+GITDIR["python-openstackclient"]=$DEST/python-openstackclient
 
 # Interactive Configuration
 # -------------------------
@@ -787,8 +787,14 @@
 # Install middleware
 install_keystonemiddleware
 
-git_clone $OPENSTACKCLIENT_REPO $OPENSTACKCLIENT_DIR $OPENSTACKCLIENT_BRANCH
-setup_develop $OPENSTACKCLIENT_DIR
+# install the OpenStack client, needed for most setup commands
+if use_library_from_git "python-openstackclient"; then
+    git_clone_by_name "python-openstackclient"
+    setup_dev_lib "python-openstackclient"
+else
+    pip_install python-openstackclient
+fi
+
 
 if is_service_enabled key; then
     if [ "$KEYSTONE_AUTH_HOST" == "$SERVICE_HOST" ]; then
@@ -1274,7 +1280,7 @@
     start_neutron_agents
 fi
 # Once neutron agents are started setup initial network elements
-if is_service_enabled q-svc; then
+if is_service_enabled q-svc && [[ "$NEUTRON_CREATE_INITIAL_NETWORKS" == "True" ]]; then
     echo_summary "Creating initial neutron network elements"
     create_neutron_initial_network
     setup_neutron_debug
diff --git a/stackrc b/stackrc
index 15b0951..18e1de3 100644
--- a/stackrc
+++ b/stackrc
@@ -144,7 +144,7 @@
 CEILOMETER_REPO=${CEILOMETER_REPO:-${GIT_BASE}/openstack/ceilometer.git}
 CEILOMETER_BRANCH=${CEILOMETER_BRANCH:-master}
 
-# volume service
+# block storage service
 CINDER_REPO=${CINDER_REPO:-${GIT_BASE}/openstack/cinder.git}
 CINDER_BRANCH=${CINDER_BRANCH:-master}
 
@@ -176,7 +176,11 @@
 NOVA_REPO=${NOVA_REPO:-${GIT_BASE}/openstack/nova.git}
 NOVA_BRANCH=${NOVA_BRANCH:-master}
 
-# storage service
+# data processing service
+SAHARA_REPO=${SAHARA_REPO:-${GIT_BASE}/openstack/sahara.git}
+SAHARA_BRANCH=${SAHARA_BRANCH:-master}
+
+# object storage service
 SWIFT_REPO=${SWIFT_REPO:-${GIT_BASE}/openstack/swift.git}
 SWIFT_BRANCH=${SWIFT_BRANCH:-master}
 
@@ -199,8 +203,8 @@
 TEMPEST_BRANCH=${TEMPEST_BRANCH:-master}
 
 # TODO(sdague): this should end up as a library component like below
-TEMPEST_LIB_REPO=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
-TEMPEST_LIB_BRANCH=${TEMPEST_LIB_BRANCH:-master}
+GITREPO["tempest_lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git}
+GITBRANCH["tempest_lib"]=${TEMPEST_LIB_BRANCH:-master}
 
 
 ##############
@@ -210,48 +214,52 @@
 ##############
 
 # ceilometer client library
-CEILOMETERCLIENT_REPO=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git}
-CEILOMETERCLIENT_BRANCH=${CEILOMETERCLIENT_BRANCH:-master}
+GITREPO["python-ceilometerclient"]=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git}
+GITBRANCH["python-ceilometerclient"]=${CEILOMETERCLIENT_BRANCH:-master}
 
 # volume client
-CINDERCLIENT_REPO=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
-CINDERCLIENT_BRANCH=${CINDERCLIENT_BRANCH:-master}
+GITREPO["python-cinderclient"]=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git}
+GITBRANCH["python-cinderclient"]=${CINDERCLIENT_BRANCH:-master}
 
 # python glance client library
-GLANCECLIENT_REPO=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git}
-GLANCECLIENT_BRANCH=${GLANCECLIENT_BRANCH:-master}
+GITREPO["python-glanceclient"]=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git}
+GITBRANCH["python-glanceclient"]=${GLANCECLIENT_BRANCH:-master}
 
 # python heat client library
-HEATCLIENT_REPO=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git}
-HEATCLIENT_BRANCH=${HEATCLIENT_BRANCH:-master}
+GITREPO["python-heatclient"]=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git}
+GITBRANCH["python-heatclient"]=${HEATCLIENT_BRANCH:-master}
 
 # ironic client
-IRONICCLIENT_REPO=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
-IRONICCLIENT_BRANCH=${IRONICCLIENT_BRANCH:-master}
+GITREPO["python-ironicclient"]=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git}
+GITBRANCH["python-ironicclient"]=${IRONICCLIENT_BRANCH:-master}
 
 # python keystone client library to nova that horizon uses
-KEYSTONECLIENT_REPO=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git}
-KEYSTONECLIENT_BRANCH=${KEYSTONECLIENT_BRANCH:-master}
+GITREPO["python-keystoneclient"]=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git}
+GITBRANCH["python-keystoneclient"]=${KEYSTONECLIENT_BRANCH:-master}
 
 # neutron client
-NEUTRONCLIENT_REPO=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git}
-NEUTRONCLIENT_BRANCH=${NEUTRONCLIENT_BRANCH:-master}
+GITREPO["python-neutronclient"]=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git}
+GITBRANCH["python-neutronclient"]=${NEUTRONCLIENT_BRANCH:-master}
 
 # python client library to nova that horizon (and others) use
-NOVACLIENT_REPO=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git}
-NOVACLIENT_BRANCH=${NOVACLIENT_BRANCH:-master}
+GITREPO["python-novaclient"]=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git}
+GITBRANCH["python-novaclient"]=${NOVACLIENT_BRANCH:-master}
+
+# python saharaclient
+GITREPO["python-saharaclient"]=${SAHARACLIENT_REPO:-${GIT_BASE}/openstack/python-saharaclient.git}
+GITBRANCH["python-saharaclient"]=${SAHARACLIENT_BRANCH:-master}
 
 # python swift client library
-SWIFTCLIENT_REPO=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git}
-SWIFTCLIENT_BRANCH=${SWIFTCLIENT_BRANCH:-master}
+GITREPO["python-swiftclient"]=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git}
+GITBRANCH["python-swiftclient"]=${SWIFTCLIENT_BRANCH:-master}
 
 # trove client library test
-TROVECLIENT_REPO=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git}
-TROVECLIENT_BRANCH=${TROVECLIENT_BRANCH:-master}
+GITREPO["python-troveclient"]=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git}
+GITBRANCH["python-troveclient"]=${TROVECLIENT_BRANCH:-master}
 
 # consolidated openstack python client
-OPENSTACKCLIENT_REPO=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git}
-OPENSTACKCLIENT_BRANCH=${OPENSTACKCLIENT_BRANCH:-master}
+GITREPO["python-openstackclient"]=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git}
+GITBRANCH["python-openstackclient"]=${OPENSTACKCLIENT_BRANCH:-master}
 
 ###################
 #
@@ -330,8 +338,8 @@
 ##################
 
 # glance store library
-GLANCE_STORE_REPO=${GLANCE_STORE_REPO:-${GIT_BASE}/openstack/glance_store.git}
-GLANCE_STORE_BRANCH=${GLANCE_STORE_BRANCH:-master}
+GITREPO["glance_store"]=${GLANCE_STORE_REPO:-${GIT_BASE}/openstack/glance_store.git}
+GITBRANCH["glance_store"]=${GLANCE_STORE_BRANCH:-master}
 
 # heat-cfntools server agent
 HEAT_CFNTOOLS_REPO=${HEAT_CFNTOOLS_REPO:-${GIT_BASE}/openstack/heat-cfntools.git}
@@ -342,12 +350,12 @@
 HEAT_TEMPLATES_BRANCH=${HEAT_TEMPLATES_BRANCH:-master}
 
 # django openstack_auth library
-HORIZONAUTH_REPO=${HORIZONAUTH_REPO:-${GIT_BASE}/openstack/django_openstack_auth.git}
-HORIZONAUTH_BRANCH=${HORIZONAUTH_BRANCH:-master}
+GITREPO["django_openstack_auth"]=${HORIZONAUTH_REPO:-${GIT_BASE}/openstack/django_openstack_auth.git}
+GITBRANCH["django_openstack_auth"]=${HORIZONAUTH_BRANCH:-master}
 
 # keystone middleware
-KEYSTONEMIDDLEWARE_REPO=${KEYSTONEMIDDLEWARE_REPO:-${GIT_BASE}/openstack/keystonemiddleware.git}
-KEYSTONEMIDDLEWARE_BRANCH=${KEYSTONEMIDDLEWARE_BRANCH:-master}
+GITREPO["keystonemiddleware"]=${KEYSTONEMIDDLEWARE_REPO:-${GIT_BASE}/openstack/keystonemiddleware.git}
+GITBRANCH["keystonemiddleware"]=${KEYSTONEMIDDLEWARE_BRANCH:-master}
 
 # s3 support for swift
 SWIFT3_REPO=${SWIFT3_REPO:-${GIT_BASE}/stackforge/swift3.git}